题目链接:http://bailian.openjudge.cn/practice/2524
2524:宗教信仰
总时间限制:
5000ms
内存限制:
65536kB
描述
世界上有许多宗教,你感兴趣的是你学校里的同学信仰多少种宗教。
你的学校有n名学生(0 < n <= 50000),你不太可能询问每个人的宗教信仰,因为他们不太愿意透露。但是当你同时找到2名学生,他们却愿意告诉你他们是否信仰同一宗教,你可以通过很多这样的询问估算学校里的宗教数目的上限。你可以认为每名学生只会信仰最多一种宗教。
输入
扫描二维码关注公众号,回复:
12445537 查看本文章

输入包括多组数据。
每组数据的第一行包括n和m,0 <= m <= n(n-1)/2,其后m行每行包括两个数字i和j,表示学生i和学生j信仰同一宗教,学生被标号为1至n。输入以一行 n = m = 0 作为结束。
输出
对于每组数据,先输出它的编号(从1开始),接着输出学生信仰的不同宗教的数目上限。
样例输入
10 9
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10
10 4
2 3
4 5
4 8
5 8
0 0
样例输出
Case 1: 1
Case 2: 7
题目理解:简单的图论的求连通分量的个数的问题,可以用DFS也可以用并查集,我直接用的并查集
AC代码:
//个人感觉就是求连通分量
#include <iostream>
#define N 50050
using namespace std;
int n,m;
int cases=1;
int ans=0;
int Tree[N];
//求连通图的连通分量的个数
int findRoot(int x){
if(Tree[x]==-1) return x;
else {
int tmp = findRoot(Tree[x]);
Tree[x] = tmp;
return tmp;
}
}
int main(){
while( cin>>n>>m){
if(n==0 && m==0) break;
for(int i=1;i<=n;i++){
Tree[i]=-1;
}
while(m--){
int a,b;
cin>>a>>b;
a=findRoot(a);
b=findRoot(b);
if(a!=b) Tree[a]=b;
}
int ans=0;
for(int i=1;i<=n;i++){
if(Tree[i]==-1)
ans++;
}
cout<<"Case "<<cases++<<": "<<ans<<endl;
}
return 0;
}