Ubiquitous Religions (并查集)

 Ubiquitous Religions

POJ - 2524 

当今世界有许多不同的宗教,很难跟踪它们。你有兴趣找出你大学里有多少不同的宗教学生相信。

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

输入

输入包括多个案例。每个案例都以指定整数 n m 的行开始。下一行由两个整数 i j 组成, 指定学生 i j 相信同一宗教。学生人数为11。输入的末端由 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

提示

巨大的输入,建议扫描。

题意描述:多实例,给学生人数以及要询问的学生对数,然后是学生相信同一宗教的学生编号,求所有学生信仰的宗教总数

解题思路:利用并查集求学生相信宗教的不相交集合,然后求一共有多少个集合即可。

AC

#include<stdio.h>
int n,m;
int s[50100]={0};
void init()
{
	for(int i=1;i<=n;i++)
		s[i]=i;
	return ;
}
//递归找爹  合并给的道路 
int getf(int v)
{
	if(s[v]==v)
		return v;
	else
	{
		//路径压缩 
		s[v]=getf(s[v]);
		return s[v]; 
	}
	
 } 
//合并两个子集
void merge(int v,int u)
{
	int t1,t2;
	t1=getf(v);
	t2=getf(u);
	if(t1!=t2)
	{
		s[t2]=t1;
	}
	return ;
 } 

int main(void)
{
	int a,b,sum,ans;
	ans=0;
	while(~scanf("%d %d",&n,&m))//学生,询问对数 
	{
		if(n+m==0)
			break;
		ans++;
		init();//初始化 
		for(int i=1;i<=m;i++)
		{
			scanf("%d %d",&a,&b);
			//合并 
			merge(a,b); 
		} 
		sum=0;
		//扫描多少个块;
		for(int i=1;i<=n;i++)
		{
			if(s[i]==i)
			sum++;
		}	
		printf("Case %d: %d\n",ans,sum);
	}
	return 0;
 } 

Guess you like

Origin blog.csdn.net/m0_58245389/article/details/120045337