首页 > 其他分享 >POJ 2524 (简单并查集)

POJ 2524 (简单并查集)

时间:2024-01-29 19:13:01浏览次数:29  
标签:2524 set int 查集 height POJ maxn find

POJ 2524 (简单并查集)

描述

当今世界上有如此多不同的宗教,很难将它们全部记录下来。您有兴趣了解您所在大学的学生信仰多少种不同的宗教。

您知道您的大学有 n 名学生 (0 < n <= 50000)。你不可能询问每个学生的宗教信仰。此外,许多学生不愿意表达自己的信仰。避免这些问题的一种方法是询问 m (0 <= m <= n(n-1)/2) 对学生,并询问他们是否信仰相同的宗教(例如,他们可能知道他们是否都参加同一所学校)教会)。从这些数据中,你可能不知道每个人信仰什么,但你可以了解校园里可能代表多少种不同宗教的上限。您可以假设每个学生最多信仰一种宗教。

输入

输入由多个案例组成。每种情况都以指定整数 n 和 m 的行开始。接下来的 m 行每行由两个整数 i 和 j 组成,指定学生 i 和 j 信仰相同的宗教。学生编号为 1 到 n。输入的结尾由 n = m = 0 的行指定。

输出

对于每个测试案例,在单行上打印案例编号(从 1 开始),后跟该大学学生信仰的不同宗教的最大数量。

Sample Input

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

Sample Output

Case 1: 1
Case 2: 7

分析,注意并查集的几个函数的优化,初始化init需要同时把每个树的高度设为1;查询find需要在内部同时更改归集,以便下次查找的复杂度为O(1);合并union中考虑每个数的高度,以便最小树高度,查询的时候耗时最低

#include <cstdio>
#include <cstring>
#define maxn 50005
int s[maxn];
int height[maxn];
void init_set(){
	for(int i = 1;i < maxn;i++){
		s[i] = i;
		height[i] = 0;
	}
} 
int find_set(int x){
	int r = x;
	while(r != s[r]) r = s[r];
	int i = x, j;
	while(i != r){
		j = s[i];
		s[i] = r;
		i = j;
	}
	return s[x];
}
void union_set(int x, int y){
	x = find_set(x);
	y = find_set(y);
	if(height[x] == height[y]){
		height[x]++;
		s[y] = s[x];
	}
	else if(height[x] < height[y]) s[x] = s[y];
	else s[y] = s[x];
}
int main() {
	int t, n, m,x, y;
	int kase = 0;
	while(scanf("%d%d", &n, &m)){
		if(n == 0 && m == 0) break;
		init_set();
		for(int i = 1;i <= m;i++){
			scanf("%d%d", &x, &y);
			union_set(x, y);
		}
		int ans = 0;
		for(int i = 1;i <= n;i++){
			if(s[i] == i) ans++;
		}
		printf("Case %d: %d\n", ++kase,ans);
	}
	return 0;
}

标签:2524,set,int,查集,height,POJ,maxn,find
From: https://www.cnblogs.com/zhclovemyh/p/17995124

相关文章

  • 并查集
    简介并查集是一种维护集合的数据结构。支持合并和查询元素所在集合。我们将所有元素用点表示,从属关系用边表示,那么每个集合构成了一棵有向树。每个点有且仅有一条出边,指向其父亲。其中根节点的出边指向自己。集合用根节点的编号代表。实现初始化一开始所有的元素指向自己。......
  • POJ--3616 Milking Time(DP)
    记录19:522024-1-26http://poj.org/problem?id=3616reference:《挑战程序设计竞赛(第2版)》第二章练习题索引p135一个LIS(最长上升子序列,LongestIncreasingSubsequence)问题的变种dp[i]表示第i个interval结尾能获得最多的milk,首先需要把数据按照起始时间排序,第i个表示......
  • POJ1129 信道分配(DFS )
    POJ1129信道分配(DFS)题目大意:每次有介于1-26个中继器,先输入一个数字n,表示中继器数量,然后一个冒号后面有与它相邻的中继器,每个中继器需要安排一个信道,不能与相邻的中继器相同,求最少的信道数量。样本输入2A:B:4A:BCB:ACDC:ABDD:BC4A:BCDB:ACDC:ABDD:ABC0示例输......
  • POJ2627 数独 (dfs or bfs)
    POJ2627数独(dfsorbfs)给出一个数独,空白用0表示,输出一个合理答案即可;SampleInput1103000509002109400000704000300502006060000050700803004000401000009205800804000107SampleOutput1436285795721394689867542313915427864689173527258639142374816956......
  • POJ1416 (dfs)
    POJ1416(dfs)公司现在要发明一种新的碎纸机,要求新的碎纸机能够把纸条上的数字切成最接近而不超过target值(可以选择不切割)。比如,target的值是50,而纸条上的数字是12346,应该把数字切成四部分,分别是1、2、34、6。因为这样所得到的和43(=1+2+34+6)是所有可能中最接近而不超......
  • 【模板】并查集
    并查集是解决两元素是否属于同一集合,将一个集合合并另一集合的数据结构。具体来说,我们使用数字代替集合,比如集合1,集合2.使用数组f[i]维护元素i属于的集合,比如f[2]=4表示元素2属于集合4。具体我们有以下实现功能的代码1初始化表示集合的数组。cin>>n>>m;for(int......
  • Codeforces Round 170 (Div. 1)A. Learning Languages并查集
    如果两个人会的语言中有共同语言那么他们之间就可以交流,并且如果a和b可以交流,b和c可以交流,那么a和c也可以交流,具有传递性,就容易联想到并查集,我们将人和语言看成元素,一个人会几种语言的话,就将这些语言和这个人所在的集合合并,最后求一下人一共在几个连通块中,连通块的个数-1就是答案,......
  • P1536 村村通(并查集)
    村村通题目描述某市调查城镇交通状况,得到现有城镇道路统计表。表中列出了每条道路直接连通的城镇。市政府"村村通工程"的目标是使全市任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要相互之间可达即可)。请你计算出最少还需要建设多少条道路?输入格式输入包含若干......
  • CF-1184-E3-最小生成树+倍增+并查集
    1184-E3题目大意给定一个\(n\)个点,\(m\)条边的无向图,边带权。对于每条边,你需要找到最大值\(x\),使得把这条边的权值修改为\(x\)后能够出现在最小生成树上。Solution先把整个图的最小生成树弄出来,然后将边分为树边以及非树边来考虑:非树边:对于一个非树边连接了\(x\)和\(y\)的......
  • 并查集与反集——P1892团伙
    并查集并查集如其名,合并与查找查找intfind(intkey){ if(fa[key]==key)returnkey; elsereturnfa[key]=find(fa[key]);}合并voidunite(intx,inty){ intfax=find(x); intfay=find(y); fa[fax]=fay; return;}反集处理并查集合并问题的敌对/......