【算法练习】图论/连通分量/并查集 poj2524:宗教信仰

题目链接: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;
}


猜你喜欢

转载自blog.csdn.net/weixin_40760678/article/details/100666965