http://poj.org/problem?id=1703
题意:
有两个帮派,有两种操作 D a b表示a 和 b不是一个帮派;A a b 表示询问a b是否是一个帮派,若至此还不确定,输出“Not sure yet”。
思路:关系并查集。只要两者的关系确定了,就将他们放入同一个集合内,而另外增加一个表示关系的数组r[ ]来表示该节点与其父亲的关系。0表示同一类,1表示不同类。初始时集合只有自己一个元素,r[ ]设置为0。
#include <stdio.h> #include <string.h> const int maxn = 100005; int n,m; int p[maxn];//保存父节点 int r[maxn];//保存与父节点的关系,0为同类。1为不同类 void make_set() { for(int i = 1; i <= n; i++) { p[i] = i; r[i] = 0; } } int find(int x) { if(x == p[x]) return x; int tmp = p[x];//记录父亲节点,方便更新r[]. p[x] = find(p[x]); r[x] = (r[x]+r[tmp])%2;//根据子节点与父亲节点的关系和父节点与爷爷节点的关系,推导子节点与爷爷节点的关系 return p[x]; } void merge(int a, int b) { int fa = find(a); int fb = find(b); p[fa] = fb; r[fa] = (r[a]+r[b]+1)%2;//fx与x关系 + x与y的关系 + y与fy的关系 = fx与fy的关系 } int main() { int test,a,b; char str[2]; scanf("%d",&test); while(test--) { scanf("%d %d",&n,&m); make_set(); while(m--) { scanf("%s %d %d",str,&a,&b); if(str[0] == ‘A‘) { if(find(a) != find(b))//如果根节点不同,则不能判断关系 { printf("Not sure yet.\n"); continue; } else { if(r[a] == r[b]) printf("In the same gang.\n"); else printf("In different gangs.\n"); } } else { merge(a,b); } } } return 0; }
poj 1703 Find them, Catch them(关系并查集)
原文:http://blog.csdn.net/u013081425/article/details/19408095