POJ_1703_Find them_并查集

来源:互联网 发布:淘宝衣服拍照技巧图片 编辑:程序博客网 时间:2024/06/03 18:02

努力,努力,再努力。


题意:

一个城市里有两帮黑社会,一共n个人,从1-n编号,需要你来鉴定他们之间的关系,提供的信息形式为某两个人不是一个组织的,在线提问某两个人的关系,要求确认在一个组织或确认不在一个组织或现在无法确认。



Input

The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. Each test case begins with a line with two integers N and M, followed by M lines each containing one message as described above.

Output

For each message "A [a] [b]" in each case, your program should give the judgment based on the information got before. The answers might be one of "In the same gang.", "In different gangs." and "Not sure yet."

并查集的小进阶。并查集可以快速查询、插入某两个元素在一个集合的信息,但是这个集合的定义是我们自己定的,并不是只能表示这两个元素属于同一个组织这样的意思,并查集的题目往往需要维护多种类型的关系,而这些关系之间又是相互影响的,这时就可以用循环数组的模式,定义在不同循环节中的两个元素在一个集合中代表什么含义。

具体到这道题,我们定义对任意两个元素a, b,如果a和b+n或者a+n和b在一个集合中(即不再同一个循环节的两个元素在一个集合中),说明a和b不属于一个组织,这样的话就能很好的完成a和b不再一个组织,b和c不在一个组织,则a和c在一个组织这样的一个效果,其实是利用了循环数组的特点。


代码如下:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<cmath>using namespace std;#define mxn 100010int father[mxn<<1];int n,m;int find(int x){return father[x]==x ? x : father[x]=find(father[x]);}void uni(int x,int y){father[find(x)]=find(y);}bool same(int x,int y){return find(x)==find(y);}void init(){for(int i=1;i<=2*n;++i)father[i]=i;}int main(){int cs,a,b;char op;scanf("%d",&cs);while(cs--){scanf("%d%d",&n,&m);init();for(int i=0;i<m;++i){getchar();scanf("%c%d%d",&op,&a,&b);if(op=='A'){if(same(a,b)||same(a+n,b+n))puts("In the same gang.");else if(same(a,b+n)||same(a+n,b))puts("In different gangs.");elseputs("Not sure yet.");}else{uni(a,b+n);uni(a+n,b);}}}return 0;}


0 0