现在的位置: 首页 > 综合 > 正文

POJ1611 The Suspects

2017年10月12日 ⁄ 综合 ⁄ 共 956字 ⁄ 字号 评论关闭

题目大意就是啊病毒又开始发作了。。。

某学校的班级开始查哪些是有可能感染流感的人

学号是从0号开始的(奇葩设定)。。。

每个班的0号都有很大的可能感染了流感(0号忒倒霉了)。。

每个班级都有一些团伙,团伙里的人都很亲密(就有有1人感染,团伙里的其他人都会感染)

输入:

每组数据:

第一行:(班级人数)(团伙个数)

然后就是描叙每一个团伙:(团伙人数)(一些学号)

对于每组数据输出可能以感染的人

主题思路就是并查集啦·~~=。=

难点就是人数的统计了

我想不出有神马好方法,但我知道对于每一棵树(所有有关联的人)只要知道其总人数就行了

关于谁谁谁有关谁谁谁无关没有弄清楚的必要(这句话就是说可以路径压缩)

于是乎如果a和b有关,我们把a所在树和b所在树和在一起就行了

(就是把a的祖宗和b的祖宗合并)

最后输出0的祖宗所在树的元素数量

值得一提的是,又要对自己和自己合并做特殊处理(普通并查集不需要)

因为涉及到元素个数的合并~!

AC代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define MAX (30000+1)
int n,m,t,mat,son,mot[MAX],num[MAX];
int find(int x)
{
	if ( x != mot[x] )
	{
		mot[x] = find(mot[x]);
	}
	return mot[x];
}
int work()
{
	for (int i = 0; i < n; i++)
	{
		mot[i] = i;
		num[i] = 1;
	}
	for (int i = 1; i <= m; i++)
	{
		scanf("%d",&t);
		if ( t < 1 )
		{
			continue;
		}
		scanf("%d",&mat);
		mat = find(mat);
		for (int j = 1; j < t; j++)
		{
			scanf("%d",&son);
			son = find(son);
			if ( son != mat )
			{
				mot[son] = mat;
				num[mat] += num[son];
			}
		}
	}
	cout<<num[find(0)];
}
int main()
{
	scanf("%d %d",&n,&m);
	work();
	while(1)
	{
		scanf("%d %d",&n,&m)
		if ( n == 0 && m == 0 )
		{
			break;
		}
		cout<<endl;
		work();
	}
	return 0;
}

抱歉!评论已关闭.