POJ 1611:The Suspects【并查集】【水题】

  POJ 1611:The Suspects

Description

严重急性呼吸系统综合症( SARS), 一种原因不明的非典型性肺炎,从2003年3月中旬开始被认为是全球威胁。为了减少传播给别人的机会, 最好的策略是隔离可能的患者。

在Not-Spreading-Your-Sickness大学( NSYSU), 有许多学生团体。同一组的学生经常彼此相通,一个学生可以同时加入几个小组。为了防止非典的传播,NSYSU收集了所有学生团体的成员名单。他们的标准操作程序(SOP)如下:

一旦一组中有一个可能的患者, 组内的所有成员就都是可能的患者。

然而,他们发现当一个学生被确认为可能的患者后不容易识别所有可能的患者。你的工作是编写一个程序, 发现所有可能的患者。

Input

输入文件包含多组数据。

对于每组测试数据:

第一行为两个整数n和m, 其中n是学生的数量, m是团体的数量。0 < n <= 30000,0 <= m <= 500。

每个学生编号是一个0到n-1之间的整数,一开始只有0号学生被视为可能的患者。

紧随其后的是团体的成员列表,每组一行。

每一行有一个整数k,代表成员数量。之后,有k个整数代表这个群体的学生。一行中的所有整数由至少一个空格隔开。

n = m = 0表示输入结束,不需要处理。

Output

对于每组测试数据, 输出一行可能的患者。

总结题意:你需要建一个n的并查集,有m个集合,最后要输出包含0的那个集合的元素的个数。(找和0结点相同的点的个数)

#include<iostream>
#include<string.h>
using namespace std;
int pre[30010],a[30010];
int find(int x)
{
	int r=x;
	while(pre[r]!=r)
	r=pre[r];
	
	int i=x;
	int j;
	while(i!=j)
	{
		j=pre[i];
		pre[i]=r;
		i=j;
	}
	return r;
	
}
void join(int x,int y)
{
	int fx=find(x);
	int fy=find(y);
	if(fx!=fy)
		pre[fx]=fy;
}
int main()
{
	int n,m,k,i,j;
	while(cin>>n>>m )
	{
		if(m==0 && n==0) break;
        if(m==0)
        {
            cout <<"1"<<endl; continue;//总觉得m=0,应该输出n 。
			//懂了,m=0,说明不划分,大家都是独立的,只有0自己有嫌疑 
        }
		for(i=0;i<n;i++)//初始化,每个人都是独立的 
		{
			pre[i]=i;
		}
		memset(a,0,sizeof(a));
		for(i=0;i<m;i++)
		{
			cin>>k;
			//if (k >= 1)                 //这三行加不加都AC 
			//{
				cin>>a[0];
				for (j = 1; j < k; j++)
				{
					cin>>a[j];
					join(a[0], a[j]);
				}
			//}

		}
		int sum=0;
		for(i=0;i<n; i++)
			if (find(i)==find(0))//和0根节点相同,说明他们是一个小组的 
				sum++;
		cout<<sum<<endl;		
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/tingtingyuan/article/details/81707407