题目:百练2524:宗教信仰
http://bailian.openjudge.cn/practice/2524/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<cmath>
#include<set>
#include<unordered_map>
using namespace std;
int n,m;
int father[50000];
int get_ancestor(int k){ //查找祖先
if(k==father[k])
return k;
else{
int ancestor=get_ancestor(father[k]);
father[k]=ancestor; //优化。每次寻找完祖先后,把这条路径上的都直接连接到祖先上
return ancestor;
}
}
void Union(int k1,int k2){ //合并两个集合,以小的为根
int ancestor1=get_ancestor(k1); //合并是对两者的祖先进行的操作
int ancestor2=get_ancestor(k2);
if(ancestor1<ancestor2)
father[ancestor2]=ancestor1;
else
father[ancestor1]=ancestor2;
}
int main(){
int TNO=0;
while(cin>>n>>m){
if(n==0 && m==0)
break;
TNO++;
for(int i=0;i<n;++i){
father[i]=i; //初始化并查集,每个点的父节点都初始成自己
}
for(int i=0;i<m;++i){
int a,b;
cin>>a>>b;
a--;
b--;
Union(a,b); //每出现一对新的关系,就合并一下两个集合
}
int total=0;
set<int> tset;
for(int i=0;i<n;++i){
auto tr=tset.insert(get_ancestor(i));
if(tr.second)
total++;
}
cout<<"Case "<<TNO<<": "<<total<<endl;
}
return 0;
}
参考博客:
https://www.jianshu.com/p/80d829aabd68