【ACM】POJ 1611 The Suspects

 

题意:
    严重急性呼吸系统综合症(SARS)是一种不明原因的非典型肺炎,在2003年3月中旬被认为是全球性威胁。为了减少传播给其他人,最好的策略是将嫌疑人与其他人分开。在不扩散你的疾病大学(NSYSU),有许多学生团体。 同一群体中的学生经常互相交流,一个学生可以参加几个小组。 为了防止可能传播的非典型肺炎,中南半球大学收集所有学生团体的成员名单,并在其标准作业程序(SOP)中作出以下规定:一旦小组中的成员是嫌疑人,小组中的所有成员都是嫌疑犯。然而,他们发现,当一名学生被确认为嫌疑犯时,识别所有嫌疑人并不容易。 你的工作是编写一个程序,找到所有的嫌疑人。
    输入文件包含几种情况。 每个测试用例都以一行中的两个整数n和m开始,其中n是学生的数量,m是组的数量。 你可以假设0 <n <= 30000和0 <= m <= 500.每个学生都用一个0到n-1之间的唯一整数进行编号,最初的学生0在所有情况下都被认为是一个嫌疑犯。 此行后面跟随m个成员组的列表,每组一行。 每行以自己的整数k开始,表示组中成员的数量。 在成员数量之后,有k个整数代表这个组中的学生。 一行中的所有整数都被至少一个空格分开。n = 0和m = 0的情况表示输入结束,不需要处理。
    对于每种情况,请输出一行中的嫌疑人人数。
解题方法:并查集
解题思路:将每个人都看作一个集合,每个小组的人员序号集合并为一个集合,合并之后,找0所在的集合有多少元素。
代码:

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=30005;
int pe[maxn];
int group[maxn];
void init(int a)
{
	for(int i=0;i<a;i++)
	{
		pe[i]=i;
	}
	return;
}
int findset(int a)//查找 
{
	while(pe[a]!=a)
	{
		a=pe[a];
	}
	return a;
}
void union_nodes(int a, int b)      //集合合并    
{    
    int a1 = findset(a);    
    int b1 = findset(b);  
    if(a1 != b1)          
    {  
        pe[a1] = b1;  
    }
	return;  
}    
int main()
{
	int n,m;
	while(~scanf("%d%d",&n,&m))
	{
		if(n==0&&m==0)
		break;
		int d,count=0;
		init(n);
		for(int i=0;i<m;i++)
		{
			scanf("%d",&d);
			for(int j=0;j<d;j++)
			scanf("%d",&group[j]);
			for(int j=1;j<d;j++)
			{
				union_nodes(group[j],group[j-1]);
			}
		}
		//printf("*%d\n",pe[0]);
		for(int i=0;i<n;i++)
		{
			if(findset(i)==findset(0))
			count++;
		}
		printf("%d\n",count);
	}
	return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值