BZOJ 1370 团伙
两个认识的人不是朋友就是敌人,且满足:
1,朋友的朋友是朋友;
2,敌人的敌人是朋友。
一群朋友组成一个团伙,给出m个信息,求有多少个团伙。
用并查集,把一个点x拆成x和x’
若a与b为朋友,则将a与b所在集合合并,这样就满足朋友的朋友是朋友;
若a与b为敌人,则将a’与b所在集合合并,将a与b’所在集合合并;这样如果a与b,b与c为敌人,那么a与b’合并,b'与c合并,则a与c在同个集合,满足敌人的敌人是朋友。
最后,统计点1~n所属于的集合的个数即为答案。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 int fa[2010],a[2010],p,x,y,n,m,ans=0; 5 void read(int &k){ 6 k=0; int f=1; char c=getchar(); 7 while (c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 8 while ('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 9 k*=f; 10 } 11 int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} 12 int main(){ 13 read(n); read(m); 14 for (int i=1;i<=2*n;i++) fa[i]=i; 15 for (int i=1;i<=m;i++){ 16 char c=getchar(); 17 read(x); read(y); 18 if (c=='F') fa[find(x)]=find(y); 19 else{ 20 fa[find(x)]=find(y+n); 21 fa[find(y)]=find(x+n); 22 } 23 } 24 for (int i=1;i<=n;i++) a[i]=find(i); 25 sort(a+1,a+n+1); 26 for (int i=1;i<=n;i++) if (a[i]!=a[i-1]) ans++; 27 printf("%d\n",ans); 28 return 0; 29 }