洛谷 P1892 [BOI2003]团伙(种类并查集)
传送门
解题思路
用并查集f存朋友关系,一个数组e存的是敌人关系,是一个辅助数组,所以叫做种类并查集。
当p和q是朋友时,直接合并,但是当是敌人时,需要一些操作。
当p还没有敌人时(即p的敌人是自己),直接e[p]=q;
否则就把p的敌人和q变成朋友,这也就是变相把p和q变成敌人。
当然,对q也是如此。
最后统计有多少人是祖先,也就是说自己的朋友是自己,统计下来。
AC代码
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int maxn=1005; 5 int f[maxn],e[maxn]; 6 int n,m; 7 char c; 8 int find(int x){ 9 if(f[x]==x) return x; 10 return f[x]=find(f[x]); 11 } 12 int ans; 13 int main(){ 14 cin>>n>>m; 15 for(int i=1;i<=n;i++) f[i]=i,e[i]=i; 16 for(int i=1;i<=m;i++){ 17 int p,q; 18 cin>>c>>p>>q; 19 if(c=='F'){ 20 f[find(p)]=find(q); 21 } 22 else{ 23 if(e[p]==p)e[p]=find(q); 24 else f[find(e[p])]=find(q); 25 if(e[q]==q)e[q]=find(p); 26 else f[find(e[q])]=find(p); 27 } 28 } 29 for(int i=1;i<=n;i++){ 30 if(f[i]==i) ans++; 31 } 32 cout<<ans; 33 return 0; 34 }