题目大意:
已知一个学校有不同的种族,给定n个人,和m对人,每对人他们的信仰一样,问n个人有多少种信仰?前提是每个人只有一个信仰
思路:如果a和b信仰相同,那么他们就属于同一集合。如果a和c相同,那么就把c加入到该集合中,很明显,属于同一集合里面的人信仰相同,那么问题就变成了求这n个人共有多少个集合。 首先,将n个人初始化为n个集合,发现a和b之间信仰相同并且它们之间不构成环的话,集合数减1,最后的集合数就是问题的答案。 这里为什么要强调不构成环,因为考虑1,2,3点,开始集合数为3,1和2之间信仰相同,集合数减1;2和3之间信仰相同,集合数减1;此时,若2和3之间信仰相同,因为2和3构成了环,所以这里集合数不需要减。 其实,构成了环,就表明从已知条件可以推出2和3信仰相同,题目给的条件是多余的信息而已。
#include <iostream>
using namespace std;
#define MAX 50010
int p[MAX];
int ans; //保存集合的数量,每个集合代表一个种族
int Find(int a){
return a==p[a]?a:Find(p[a]);
}
void Union(int u,int v){
int x = Find(u);
int y = Find(v);
if(x!=y){
ans--;
p[x] = y;
}
}
int main(){
int n,m,i;
int a,b;
int num = 0;
while(cin>>n>>m){
num++;
for(i=0;i<n;i++){
p[i] = i;
}
ans = n; //初始化每个点代表一个集合
if(n==0&&m==0) break;
for(i=0;i<m;i++){
cin>>a>>b;
Union(a,b);
}
cout<<"Case "<<num<<": "<<ans<<endl;
}
return 0;
}