疑似病人(并查集)

来源:互联网 发布:数据分析和前端 编辑:程序博客网 时间:2024/04/29 08:27

Link:点击打开链接


疑似病人

Time Limit 1000ms

Memory Limit 65536K

description

严重急性呼吸系统综合症(SARS),是一个未知的非典型性肺炎的病。在2003年三月中旬被公认为全球的威胁。为了减少传播给他人的可能,最好的策略是把疑似病人与其他人分隔开来。          在Not-Spreading-Your-Sickness大学(中山),有许多学生团体。 同一组的学生经常互相交往,学生可以参加多个团体。为了减少“非典”传播的可能,Not-Spreading-Your-Sickness大学搜集所有学生团体的学生会员名单,并且使下列规则作为他们的标准操作规程(SOP)。   一旦一个会员是一个嫌疑人,在团体所有成员都成为嫌疑人。然而,他们发现这并不容易确认学生就是疑似病人。你的任务是编写一个程序,发现所有的疑似病人。

input

输入多组数据。每个测试数据始于两整数n和m,n是学生的数量,m是团体的个数。你可能认为0 < n < = 30000和0 < = m < = 500。每一位学生都被编上一个从0到n-1的独特的数,并且学生0是公认的疑似病人。该行后面紧接是每个团体的成员名单,每个团队一行。每一行的第一个数k代表该团体的成员人数。之后是k个数据,代表该团体的学生。所有在一行的数据之间至少用一个空格隔开。案例由n = 0,m = 0表示结束的输入,且不需要处理。

output

对于每组数据,输出疑似病人的个数,输出仅包括一行。

sample_input

100 42 1 25 10 13 11 12 142 0 12 99 2200 21 55 1 2 3 4 51 00 0

sample_output

411

hint

source




#include<stdio.h>
int n,m,pre[30000],rank[30000];
void init()
{
int i;
for(i=0;i<n;i++)
{
pre[i]=i;
rank[i]=1;
}
}
int find(int root)
{
int son,tmp;
son=root;
while(root!=pre[root])
{
root=pre[root];
}
    while(son!=root)
{
tmp=pre[root];
pre[son]=root;
son=tmp;
}
return root;
}
void join(int root1,int root2)
{
int x,y;
x=find(root1);
y=find(root2);
if(x!=y)
{
if(x<y)
{
pre[y]=x;
rank[x]+=rank[y];
}
else
{
pre[x]=y;
rank[y]+=rank[x];
}
}
}
int main()
{
int k,t,a;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0)
break;
init();
while(m--)
{
scanf("%d",&k);
t=-1;
while(k--)
{
scanf("%d",&a);
if(t!=-1)
join(a,t);
t=a;
}
}
printf("%d\n",rank[0]);
}
return 0;
}


0 0