并查集
查询两个集合中是否有相同的元素,如果有,合并成一个集合;没有就算了
拿oj上一道题来说
1526:宗教信仰
描述
世界上有许多宗教,你感兴趣的是你学校里的同学信仰多少种宗教。
你的学校有n名学生(0 < n <= 50000),你不太可能询问每个人的宗教信仰,因为他们不太愿意透露。但是当你同时找到2名学生,他们却愿意告诉你他们是否信仰同一宗教,你可以通过很多这样的询问估算学校里的宗教数目的上限。你可以认为每名学生只会信仰最多一种宗教。
输入
输入包括多组数据。
每组数据的第一行包括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
解题思路,让每个人都初始化信仰一个宗教,这样就有n个宗教;然后查看两个人信仰的宗教是否相同,相同就合为一个宗教,宗教数变为n-1等等
#include<bits/stdc++.h>
using namespace std;
int pre[50004];//pre[i]代表i的上级
int n,m;
int find(int root)//查找root的最上级
{
int son,tmp;
son=root;
while(root!=pre[root])//查找最上级,上级是自己的就是最上级
root=pre[root];//找到了,最上级赋值给root
while(son!=root)//压缩,让每个下级的上级都是最上级
{
tmp=pre[son];
pre[son]=root;
son=tmp;
}
return root;
}
void join(int x,int y)//合并
{
x=find(x);//找到x的最上级
y=find(y);//找到y的最上级
if(x!=y)//判断x和y的最上级是否是同一个人,不是的话就合并这两个集体
{
pre[x]=y;//谁是最上级都无所谓,pre[y]=x也对
n--;//宗教数-1
}
//是同一个人的话那就说明两人本就是同一个集体
}
int main()
{
int cot=0;
while(cin>>n>>m && n,m)
{
for(int i=1;i<=n;i++)
pre[i]=i;//初始化,有n个宗教
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
join(x,y);//合并两个集体
}
cout<<"Case "<<++cot<<": "<<n<<endl;;
}
return 0;
}
代码不会错,已通过

并查集就是个模板,想要彻底了解并查集的可以点击此处看这篇文章
本文介绍了一种使用并查集算法解决的问题:通过一系列学生之间的宗教信仰关系查询来估算学校里宗教种类数量的上限。该算法能够高效地合并具有相同宗教信仰的学生群体,并计算最终的宗教类别总数。
8741

被折叠的 条评论
为什么被折叠?



