POJ 1703 Find them, Catch them【并查集】
题意: 有 N 个人分属于两个帮派,对应两种操作:
A X Y 询问x,y 是否属于一个帮派,或两者关系不能确定。
D X Y X和Y 分属不同帮派
分析: 感觉就是简化版的食物链...
方法一:
加一个数组 r[i]
r[i] = 0 表示 i 与祖先属于同一个帮派
r[i] = 1 表示 i 与祖先属于不同帮派
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<string.h> int f[100005]; int r[100005]; int find(int x) { int s; if(f[x]==-1) return x; else s=find(f[x]); r[x]=(r[x]+r[f[x]])%2; f[x]=s; return s; } void join(int x,int y) { int fx=find(x); int fy=find(y); if(fx!=fy) { f[fy]=fx; r[fy]=(r[x]+r[y]+1)%2; } } int main() { char c[2]; int t,i,a,b,n,m,fx,fy; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++){ f[i]=-1; r[i]=0; } // scanf("%c",&c); while(m--) { scanf("%s%d%d",c,&a,&b); if(c[0]=='A') { fx=find(a); fy=find(b); if(fx==fy) { if(r[a]==r[b]) printf("In the same gang.\n"); else printf("In different gangs.\n"); } else printf("Not sure yet.\n"); } else join(a,b); // scanf("%c",&c); } } return 0; }
方法二:
对于每一个人 i ,都假设 i + n 和他对立,假如 j 和 i+n 对立,那么 j 和 i 必属与于同一个派别,若 j 和 i+n属于同一个集合,那么i 和 j 一定对立。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<string.h> int f[200005]; int find(int x) { return f[x]==x?x:(f[x]=find(f[x])); } void join(int x,int y) { int fx=find(x); int fy=find(y); if(fx!=fy) f[fy]=fx; } int main() { char s[2]; int t,n,m,a,b,fx,fy,i; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(i=1;i<=2*n;i++) f[i]=i; while(m--) { scanf("%s%d%d",s,&a,&b); if(s[0]=='A') { if(find(a+n)==find(b)) printf("In different gangs.\n"); else if(find(a)==find(b)) printf("In the same gang.\n"); else printf("Not sure yet.\n"); } else { join(a,b+n); join(b,a+n); } } } return 0; }