Live2D

POJ2425 Ubiquitous Religions(并查集板题)

题目链接:POJ2425 Ubiquitous Religions
题目翻译:
一个大学中有n(编号由1~n)个学生,我们无法确定他们分别信仰什么宗教,但我们可以确定有m对同学信仰相同的宗教
现给出这m对同学的编号,请问他们最多信仰多少种不同的宗教?
输入格式:
现在有若干对的数据,输入n,m,当n == 0且m == 0时结束输入
每一对数据分为m+1行,第1行输入n,m,第2~m+1行输入这m对同学的关系
输出格式:
假设现在输入的是第tot对数据,输出“Case tot: ans\n”(不带引号)
样例解释:(见题面,请自行手模)


问题分析:
就是最开始是有n个连通块,每次判断一下

  1. 如果他们已经在同一连通块内,那么没有必要再把他们加到连通块内
  2. 否则,连通块的个数要减一,并且将他们加到同一连通块内
    最后放出代码:
#include <cstdio>
#include <iostream>
using namespace std;
int read() {
	int w = 1,res = 0;
	char ch = getchar();
	while(ch < '0' || ch > '9') {
		if(ch == '-') w = -1;
		ch = getchar();
	}
	while(ch >= '0' && ch <= '9') res = res * 10 + ch - '0', ch = getchar();
	return w * res;
}
int pre[50010];                                          //并查集父亲数组
int find(int k) {
	return k == pre[k] ? k : pre[k] = find(pre[k]);  //路径压缩加上求祖先
}
int main() {
	int n, m, tot = 0;
	while(cin >> n >> m) {
		if(n == 0 && m == 0) return 0;
		int ans = n;                             //最开始有n个连通块
		for(int i = 1; i <= n; i ++) pre[i] = i; //把自己定义成自己的父亲
		while(m --) {
			int a = read(), b = read();      //a,b信仰同一宗教
			if(find(a) != find(b)) {         //如果他们不在同一连通块内
				ans --;                  //那么总连通块数--
				pre[find(a)] = find(b);  //将其加入到同一连通块内
			}
		}
		printf("Case %d: %d\n", ++ tot,  ans);   //按格式输出
	}
}
posted @ 2020-10-02 13:06  Wuzhouming  阅读(92)  评论(0编辑  收藏  举报