POJ - 1984 Navigation Nightmare 种类并查集
思路:记录每个点与其根结点的横向距离和纵向距离,当知道其父节点与根结点的关系,很容易推出当前节点与根结点的关系:
直接相加即可。
int p = a[x].par; a[x].dx += a[p].dx; a[x].dy += a[p].dy;
合并什么的就不多说了,很容易得出。
值得一说的就是需要按照合并节点的顺序把询问排序,最后按照询问的顺序再排一次序。
AC代码
#include <cstdio>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define eps 1e-10
#define inf 0x3f3f3f3f
#define PI pair<int, int>
typedef long long LL;
const int maxn = 40000 + 5;
struct node{
int par;
int dx, dy;
}a[maxn];
struct Edge{
int u, v, dis, ch;
}b[maxn];
struct Question{
int u, v, t, num;
}q[10000+5];
void init(int n) {
for(int i = 1; i <= n; ++i) {
a[i].par = i;
a[i].dx = a[i].dy = 0;
}
}
int find(int x) {
if(a[x].par == x) return x;
int r = find(a[x].par);
int p = a[x].par;
a[x].dx += a[p].dx;
a[x].dy += a[p].dy;
return a[x].par = r;
}
void unionset(int x, int y, int dx, int dy) {
int rx = find(x), ry = find(y);
if(rx != ry) {
a[rx].par = y;
a[rx].dx = dx - a[x].dx;
a[rx].dy = dy - a[x].dy;
}
}
int get_dis(int x, int y) {
int rx = find(x), ry = find(y);
if(rx != ry) return -1;
return abs(a[x].dx - a[y].dx) + abs(a[x].dy - a[y].dy);
}
bool cmp1(const Question &a, const Question &b) {
return a.t < b.t;
}
bool cmp2(const PI &a, const PI &b) {
return a.second < b.second;
}
int main() {
int n, m, Q;
while(scanf("%d%d", &n, &m) == 2) {
init(n);
for(int i = 1; i <= m; ++i) {
scanf("%d %d %d %c", &b[i].u, &b[i].v, &b[i].dis, &b[i].ch);
//printf("%d %d %d %c\n", b[i].u, b[i].v, b[i].dis, b[i].ch);
}
scanf("%d", &Q);
for(int i = 1; i <= Q; ++i) {
scanf("%d%d%d", &q[i].u, &q[i].v, &q[i].t);
q[i].num = i;
}
vector<PI>ans;
sort(q+1, q+Q+1, cmp1);
int ind = 1;
for(int i = 1; i <= m; ++i) {
int dx, dy;
switch(b[i].ch) {
case 'E': dx = b[i].dis, dy = 0; break;
case 'W': dx = -b[i].dis, dy = 0; break;
case 'N': dx = 0, dy = b[i].dis; break;
case 'S': dx = 0, dy = -b[i].dis; break;
}
unionset(b[i].u, b[i].v, dx, dy);
while(ind <= Q && q[ind].t == i) {
ans.push_back(make_pair(get_dis(q[ind].u, q[ind].v), q[ind].num));
++ind;
}
}
sort(ans.begin(), ans.end(), cmp2);
for(int i = 0; i < ans.size(); ++i) printf("%d\n", ans[i].first);
}
return 0;
}
如有不当之处欢迎指出!
POJ - 1984 Navigation Nightmare 种类并查集的更多相关文章
- POJ1984 Navigation Nightmare —— 种类并查集
题目链接:http://poj.org/problem?id=1984 Navigation Nightmare Time Limit: 2000MS Memory Limit: 30000K T ...
- POJ 1984 Navigation Nightmare 【经典带权并查集】
任意门:http://poj.org/problem?id=1984 Navigation Nightmare Time Limit: 2000MS Memory Limit: 30000K To ...
- poj 1182:食物链(种类并查集,食物链问题)
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 44168 Accepted: 12878 Description ...
- poj 1182 食物链(种类并查集 ‘初心者’)
题目链接:http://poj.org/problem?id=1182 借着这题可以好好理解一下种类并查集,这题比较简单但挺经典的. 题意就不解释了,中问题. 关于种类并查集结局方法也是挺多的 1扩增 ...
- POJ 1984 Navigation Nightmare 带全并查集
Navigation Nightmare Description Farmer John's pastoral neighborhood has N farms (2 <= N <= ...
- POJ 1984 - Navigation Nightmare - [带权并查集]
题目链接:http://poj.org/problem?id=1984 Time Limit: 2000MS Memory Limit: 30000K Case Time Limit: 1000MS ...
- POJ 1984 Navigation Nightmare(二维带权并查集)
题目链接:http://poj.org/problem?id=1984 题目大意:有n个点,在平面上位于坐标点上,给出m关系F1 F2 L D ,表示点F1往D方向走L距离到点F2,然后给出一系 ...
- poj 1984 Navigation Nightmare(带权并查集+小小的技巧)
题目链接:http://poj.org/problem?id=1984 题意:题目是说给你n个线,并告知其方向,然后对于后面有一些询问,每个询问有一个时间点,要求你输出在该时间点a,b的笛卡尔距离,如 ...
- POJ 1182 食物链(种类并查集)
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 63592 Accepted: 18670 Description ...
随机推荐
- python_鸡兔同笼问题
鸡兔同笼问题 -- 今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何? --鸡和兔在一个笼子里,从上面数,有35个头:从下面数,有94只脚.问笼中各有几只鸡和兔 如何逻辑整理? -- 鸡头和兔子 ...
- python_如何修改装饰器中参数?
案例: 为分析程序内哪些函数执行时间开销较大,我们需定义一个带timeout参数的装饰器 需求: 统计被装饰函数的运行时间 时间大于timeout时,将此次函数调用记录到log日志中 运行时可以修改t ...
- 在CMainFrame里使用定时器是有讲究的
设置定时器函数:SetTimer 单位毫秒 销毁定时器函数:KillTimer 消息:WM_TIMER 注意事项: (1)不要在构造函数里设置定时器. (2)不要在析构函数里销毁定时器. 原因:构造函 ...
- java常用类--正则表达式
正则表达式到底是什么? 在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要.正则表达式就是用于描述这些规则的工具.换句话说,正则表达式就是记录文本规则的代码. 很可能你使用过W ...
- 将centos_yum源更换为阿里云(官方文档)
http://mirrors.aliyun.com/help/centos?spm=5176.bbsr150321.0.0.d6ykiD 1.备份 mv /etc/yum.repos.d/CentOS ...
- SpringMVC实现PUT请求上传文件
在JQuery中,我们可以进行REST ful中delete和put的请求,但是在java EE标准中,默认只有在POST请求的时候,servlet 才会通过getparameter()方法取得请求体 ...
- Single-Pass Stereo Rendering for HoloLens——HoloLens的单程立体渲染
原文网站:https://docs.unity3d.com/Manual/SinglePassStereoRenderingHoloLens.html Single-Pass Stereo Rende ...
- 解决苹果电脑(mac)管理员账户变成了普通用户后不能解锁用户与群组的问题
亲们,我先说说前因,然后再说一下解决方法. 前因 今天不知怎么就想把苹果电脑原来的名字给改一下,于是就做了下面的操作(你们不要这样做) 1.系统偏好设置→用户与组群→当前管理员用户→(右键)高级选项 ...
- MongoDB Driver 简单的CURD
c#中我们可以使用MongoDB.Driver驱动进行对MongoDB数据库的增删改查. 首先需要在NuGet中安装驱动 安装完毕后会发现会有三个引用 其中 MongoDB.Driver和MongoD ...
- 小白学Docker之Compose
承接上篇文章:小白学Docker之基础篇,自学网站来源于https://docs.docker.com/get-started 概念 Compose是一个编排和运行多容器Docker应用的工具,主要是 ...