http://poj.org/problem?id=1703
题目大意:
有一些罪犯,分两伙 每伙至少一个
两种操作
D a b:a和b不是一伙的
A a b:a和b 之间的关系是什么
思路:
并查集,先把可以确定关系的罪犯放在一个集里 再多一个数组
表示此节点和他指向的上一个节点是否一样(是否同伙)
代码及其注释:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<queue> #include<algorithm> #include<set> using namespace std; const int N=100010; int f[N];//他指向的上一个节点 int same[N];//和他指向的上一个节点是否同伙 1表示同伙 0表示不同伙 int findf(int x) { if(f[x]!=x) { int temp=f[x];//暂存 f[x]=findf(f[x]); if(same[x]==same[temp])//更新所指向节点后 关系也要更新 { same[x]=1; }else { same[x]=0; } } return f[x]; } int main() { int T; scanf("%d",&T); while(T--) { int n,m; scanf("%d %d",&n,&m); for(int i=1;i<=n;++i) { f[i]=i; same[i]=1; } while(m--) { char c; int x,y; getchar(); scanf("%c %d %d",&c,&x,&y); if(c=='D') { int xf=findf(x); int yf=findf(y); f[xf]=yf; if(same[x]==same[y]) { same[xf]=0; }else { same[xf]=1; } }else { if(n==2)//注意只有2个人的情况 { printf("In different gangs.\n"); continue; } if(findf(x)!=findf(y))//是否可以确定关系 而且经过findf()函数 此点已经指向根节点 { printf("Not sure yet.\n"); }else if(same[x]==same[y])//和根节点的关系是否一样 { printf("In the same gang.\n"); }else { printf("In different gangs.\n"); } } } } return 0; }