原题地址:《The Suspecst》
题目大意:某学校有N个学生,M个社团,每个学生可以属于多个社团。SARS流行,但是社团活动频繁,一旦一个社团有一个人是SARS疑似,所有人都是SARS疑似。现在假定第0号学生是SARS疑似,求所有疑似病例。
这个就是典型的并查集问题……我挑了这个最水的问题实践了一下。和刚才哪篇并查集无异。数据弱所以连rank union都不用就能过。
思路是:每个社团读取后直接把他们union起来。最后将学生0的parent和其他N-1个学生比较(来判断他们是否属于一个集合),如果一样的,sum++。最后输出sum。
代码是有优化余地的:实际上,每次union的时候就能知道每个set有多少新元素。这样就不用最后再遍历依次n个学生的find_set了!
#include <stdio.h>
#define MAX 30001
int parent[MAX];
int num[MAX];
int find_set(int x)
{
if(x!=parent[x])
{
int tmp = find_set(parent[x]);
parent[x] = tmp;
}
return parent[x];
}
int union_set(int x, int y)
{
int x_parent = find_set(x);
int y_parent = find_set(y);
parent[x_parent] = parent[y_parent];
}
int main()
{
int n,m;
int i, j;
int k;
int first;
int member;
int sus;
int sum;
while(scanf("%d %d", &n, &m)!=EOF)
{
if(n==0 && m==0)
{
break;
}
// Init set
for(i=0;i<n;i++)
{
parent[i] = i;
}
// Read each group and union member in each group
for(i=0;i<m;i++)
{
scanf("%d", &k);
scanf("%d", &first);
for(j=1;j<k;j++)
{
scanf("%d", &member);
union_set(first, member);
}
}
// Get suspect [0]'s parent
int sus = find_set(0);
sum = 0;
for(i=0;i<n;i++)
{
if(find_set(i)==sus)
{
sum++;
}
}
printf("%d\n", sum);
}
}