思路:记录每个点与其根结点的横向距离和纵向距离,当知道其父节点与根结点的关系,很容易推出当前节点与根结点的关系:

直接相加即可。

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 种类并查集的更多相关文章

  1. POJ1984 Navigation Nightmare —— 种类并查集

    题目链接:http://poj.org/problem?id=1984 Navigation Nightmare Time Limit: 2000MS   Memory Limit: 30000K T ...

  2. POJ 1984 Navigation Nightmare 【经典带权并查集】

    任意门:http://poj.org/problem?id=1984 Navigation Nightmare Time Limit: 2000MS   Memory Limit: 30000K To ...

  3. poj 1182:食物链(种类并查集,食物链问题)

    食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 44168   Accepted: 12878 Description ...

  4. poj 1182 食物链(种类并查集 ‘初心者’)

    题目链接:http://poj.org/problem?id=1182 借着这题可以好好理解一下种类并查集,这题比较简单但挺经典的. 题意就不解释了,中问题. 关于种类并查集结局方法也是挺多的 1扩增 ...

  5. POJ 1984 Navigation Nightmare 带全并查集

    Navigation Nightmare   Description Farmer John's pastoral neighborhood has N farms (2 <= N <= ...

  6. POJ 1984 - Navigation Nightmare - [带权并查集]

    题目链接:http://poj.org/problem?id=1984 Time Limit: 2000MS Memory Limit: 30000K Case Time Limit: 1000MS ...

  7. POJ 1984 Navigation Nightmare(二维带权并查集)

    题目链接:http://poj.org/problem?id=1984 题目大意:有n个点,在平面上位于坐标点上,给出m关系F1  F2  L  D ,表示点F1往D方向走L距离到点F2,然后给出一系 ...

  8. poj 1984 Navigation Nightmare(带权并查集+小小的技巧)

    题目链接:http://poj.org/problem?id=1984 题意:题目是说给你n个线,并告知其方向,然后对于后面有一些询问,每个询问有一个时间点,要求你输出在该时间点a,b的笛卡尔距离,如 ...

  9. POJ 1182 食物链(种类并查集)

    食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 63592   Accepted: 18670 Description ...

随机推荐

  1. TypeError: 'encoding' is an invalid keyword argument for this function

    python 2.7 问题 data_file = open("F:\\MyPro\\data.yaml", "r", encoding='utf-8') 运行 ...

  2. aliyun 购买的linux安装tomcat

    按照网上的教程,下载tomcat,解压(即安装),启动,发现无法访问.有说端口未开放,修改/etc/sysconfig/iptables,添加端口开放.未发现有此文件,只有iptables-confg ...

  3. android软键盘的显示和隐藏

    显示: InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); imm.toggle ...

  4. 【转】<string> <string.h> <cstring>的区别

    #include < string.h > void main() { string aaa = " abcsd d " ; printf( " lookin ...

  5. 【转】centos安装vim7.4

    centos安装vim7.4   系统版本centos6.4; root权限 su - root     卸载 $ rpm -qa | grep vim $ yum remove vim vim-en ...

  6. 文件无法删除java.io.IOException: Unable to delete

    疑问:1.为什么调用file.delete()方法时,返回值为false. 2.为什么调用Guava工具jar包中的Files.move(from,to) ,报异常:java.io.IOExcepti ...

  7. Effective Java 之-----返回零长度的数组或集合而不是null

    如下代码,通常用户列表为空时,会习惯性返回null,因为这时会认为:null返回值比零长度数组更好,因为它避免了分配数组所需要的开销. private final List<UserBean&g ...

  8. oracle用户、权限操作

    oracle用户操作,权限操作: 1.创建用户,并让用户默认表空间为tb1: create user 用户名 identified by 密码 default namespace tb1 2.授权: ...

  9. CentOS下mysql数据库data目录迁移和配置优化

    目录迁移 关闭数据库服务 service mysqld stop 复制数据库 mv /var/lib/mysql /data/mysql # 或者使用cp -a复制 # 这两个命令都会带权限到新目录去 ...

  10. java多线程之内存可见性-synchronized、volatile

    1.JMM:Java Memory Model(Java内存模型) 关于synchronized的两条规定: 1.线程解锁前,必须把共享变量的最新值刷新到主内存中 2.线程加锁时,将清空工作内存中共享 ...