1.题意
新型冠状病毒肺炎(Corona Virus Disease 2019,COVID-19),简称“新冠肺炎”,是指2019新型冠状病毒感染导致的肺炎。
如果一个感染者走入一个群体,那么这个群体需要被隔离!
小A同学被确诊为新冠感染,并且没有戴口罩!!!!!!
危!!!
时间紧迫!!!!
需要尽快找到所有和小A同学直接或者间接接触过的同学,将他们隔离,防止更大范围的扩散。
众所周知,学生的交际可能是分小团体的,一位学生可能同时参与多个小团体内。
请你编写程序解决!戴口罩!
2.样例
Input
多组数据,对于每组测试数据:
第一行为两个整数n和m(n = m = 0表示输入结束,不需要处理),n是学生的数量,m是学生群体的数量。0 < n <= 3e4 , 0 <= m <= 5e2
学生编号为0~n-1
小A编号为0
随后,m行,每行有一个整数num即小团体人员数量。随后有num个整数代表这个小团体的学生。
Output
输出要隔离的人数,每组数据的答案输出占一行
Sample Input
100 4
2 1 2
5 10 13 11 12 14
2 0 1
2 99 2
200 2
1 5
5 1 2 3 4 5
1 0
0 0
Sample Output
4
1
1
3.解题思路
- 该题是对并查集的考察
- 并查集初始化,指示n个元素,它们独自是一个分组,初始化即标识代表元是其本身
- 并查集查找,路径压缩,把自己挂在根结点下
- 并查集的合并,小树挂在大树下,用数组sum记录当前集合大小
- 用一个数h来标记该元素是否是集合的第一个元素,是则继续,否则合并上一个元素,数组vis标记该元素是否第一次出现,第一次出现则标记且初始化sum[x]=1,否则与之前出现的集合进行合并
4.AC代码
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
const int M=3e4+5;
int pa[M];
int vis[M];
int sum[M];
void swap(int &x,int &y)
{
int temp=x;
x=y;
y=temp;
}
int find(int x)
{
if(pa[x]==x) return x;
return pa[x]=find(pa[x]);
}
bool unite(int x,int y)
{
x=find(x);
y=find(y);
if(x==y) return false;
if(sum[x]>sum[y]) swap(x,y);
pa[x]=y;
sum[x]+=sum[y];
sum[y]=sum[x];
return true;
}
int main()
{
int m,n,k,a,h=-1;
while(cin>>n>>m)
{
memset(pa,0,sizeof(pa));
memset(vis,0,sizeof(vis));
memset(sum,0,sizeof(sum));
sum[0]=1;
if(n==0&&m==0) break;
for(int i=0;i<n;i++)
{
pa[i]=i;
}
for(int i=0;i<m;i++)
{
cin>>k;
h=-1;
for(int j=0;j<k;j++)
{
cin>>a;
if(vis[a]==0)
{
vis[a]=1;
sum[a]=1;
}
else{
int f=find(a);
unite(a,f);
}
if(h!=-1)
{
unite(a,h);
}
h=a;
}
}
cout<<sum[find(0)]<<endl;
}
}