题目描述
1920年的芝加哥,出现了一群强盗。如果两个强盗遇上了,那么他们要么是朋友,要么是敌人。而且有一点是肯定的,就是:
我朋友的朋友是我的朋友;
我敌人的敌人也是我的朋友。
两个强盗是同一团伙的条件是当且仅当他们是朋友。现在给你一些关于强盗们的信息,问你最多有多少个强盗团伙。
输入输出格式
输入格式:
输入文件gangs.in的第一行是一个整数N(2<=N<=1000),表示强盗的个数(从1编号到N)。 第二行M(1<=M<=5000),表示关于强盗的信息条数。 以下M行,每行可能是F p q或是E p q(1<=p q<=N),F表示p和q是朋友,E表示p和q是敌人。输入数据保证不会产生信息的矛盾。
输出格式:
输出文件gangs.out只有一行,表示最大可能的团伙数。
输入输出样例
输入样例#1:
6 4 E 1 4 F 3 5 F 4 6 E 1 2
输出样例#1:
3
--------------------------------------------------------
分析:维护这种有传递性的父子关系,当然用并查集啦!
求助:问一个问题,为什么两人(a , b)是朋友时不用unite(a+n,b+n),但2024食物链却要unite(a,b) unite(a+n,b+n) unite(a+n*2,b+n*2),知道的能不能在下面评论一下,谢谢啦。
#include <cstdio> #include <algorithm> using namespace std; const int maxn=2050; int pa[maxn],table[maxn],rank[maxn],n;//num是以i为根的团伙数 void init() { for(int i=0;i<maxn;i++) { pa[i]=i; } } int find(int x) { if(pa[x]==x) return x; else return pa[x]=find(pa[x]); } void unite(int x,int y) { x=find(x); y=find(y); if(x==y) return; if(rank[x]<rank[y]) pa[x]=y; else { pa[y]=x; if(rank[x]==rank[y]) rank[x]++; } return; } int main() { int m,maxnum=0; char s[10]; scanf("%d%d",&n,&m); init(); for(int i=0;i<m;i++) { int a,b; scanf("%s%d%d",s,&a,&b); if(s[0]=='F') { unite(a,b); // unite(a+n,b+n); } else { unite(a,b+n); unite(a+n,b); } } for(int i=1;i<=n;i++) table[find(i)]=1;//有多少团伙 for(int i=1;i<=2*n;i++) if(table[i]==1) maxnum++; printf("%d",maxnum); return 0; }