Poj 2524 Ubiquitous Religions

题目大意:输入n和m,n代表一共有n个学生,m代表接下来要输入m行,每行有两个数字表示这两个学生信奉同一个宗教,要求输出这n个人的信教一共有多少种。

思路:典型的并查集应用,统计宗教个数的时候借用了STL中的map。

#include <iostream>
using namespace std;
#include <map>
#include <memory.h>
#include <stdio.h>
// Model 1
const int MAXSIZE = 50010;
int rank[MAXSIZE];//rank[x]表示x的秩
int parent[MAXSIZE];
int n;//集合元素,从1到n
map<int ,int> flag;
/* 查找x元素所在的集合,回溯时压缩路径*/
int FindSet(int x) {
	if (x!=parent[x])
		parent[x]=FindSet(parent[x]);
	return parent[x];
}
//Union按秩合并,即合并的时候将元素少的集合合并到元素多的集合中,这样合并之后树的高度会相对较小
//通过秩rank的大小来衡量元素的多少
void Union(int root1, int root2) {
	int x=FindSet(root1),y=FindSet(root2);
	if (x==y)
		return;
	if (rank[x]>rank[y])
		parent[y]=x;
	else {
		parent[x]=y;
		if (rank[x]==rank[y])
			++rank[y];
	}
}
void Initialization() {
	int i;
	memset(rank,0,sizeof(rank));
	for (i=1;i<=n;i++)
		parent[i]=i;
}
int main()
{
	int m,i,t;
	int x,y;

	scanf("%d%d",&n,&m);
	t=1;
	while (!(n==0&&m==0)) {
		Initialization();
		flag.clear();
		for (i=0;i<m;i++) {
			scanf("%d%d",&x,&y);
			Union(x,y);
		}
		for (i=1;i<=n;i++)
			flag[FindSet(i)]=1;
		printf("Case %d: %d\n",t,flag.size());
		t++;
		scanf("%d%d",&n,&m);
	}
	return 0;
} 


你可能感兴趣的:(Poj 2524 Ubiquitous Religions)