算法笔记--并查集模板 题openjudge - 1526:宗教信仰

本文介绍了一种使用并查集算法解决的问题:通过一系列学生之间的宗教信仰关系查询来估算学校里宗教种类数量的上限。该算法能够高效地合并具有相同宗教信仰的学生群体,并计算最终的宗教类别总数。

并查集

查询两个集合中是否有相同的元素,如果有,合并成一个集合;没有就算了
拿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;
}

代码不会错,已通过


并查集就是个模板,想要彻底了解并查集的可以点击此处看这篇文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值