题目:
2019冠状病毒病(英语:Coronavirus disease 2019,缩写:COVID-19 ),是一种由严重急性呼吸系统综合症冠状病毒2型(缩写:SARS-CoV-2)引发的传染病。此病在全球各国大规模爆发并急速扩散,成为人类历史上致死人数最多的流行病之一。 很显然,目前最好的办法就是将所有可能的患者都隔离起来。 现在某高校正在排查可能的患者,这个高校中有多个社团,每个社团经常进行内部交流,一名学生可能会加入多个社团。学校认为一旦某个社团里出现一名可疑患者,这整个社团的学生都被视为是可能的患者。 现在请你帮忙找到这所学校的所有可能的患者。
Input
输入文件包含多组数据。
对于每组测试数据:
第一行为两个整数n和m, 其中n是学生的数量, m是社团的数量。0 < n <= 30000,0 <= m <= 500。
接下来m行,每一行有一个整数k,代表社团中学生的数量。之后,有k个整数代表这个社团里每个学生的编号(在0到n-1之间)。
n = m = 0表示输入结束,不需要处理。
Output
对于每组测试数据, 输出可能的患者数目。
Sample Input
100 4 2 1 2 5 11 13 50 12 14 2 0 1 2 99 2 200 2 1 5 6 5 6 7 8 9 10 1 0 0 0
Sample Output
4 1 1
题解:这题少说了个条件,编号为0的学生固定为可疑患者。我们只要将每个社团中的人做一个连通图,再判断每个人的最终父亲节点是否与0号同学的节点相同即可。
代码:
#include <iostream>
#include <algorithm>
using namespace std;
int q[30001];
bool bb[30001];
inline int find(int a)
{
if (q[a]!=a) q[a]=find(q[a]);//找节点同时更新父亲节点的值,减少时间
return q[a];
}
inline void jiehe(int x,int y)
{
int d=find(x);int dd=find(y);//找最终父亲节点
if (d==dd) return;//相同不用再结合
if (d==0) q[dd]=q[d]; else q[d]=q[dd];//确保0的最终父亲节点是0
}
inline void solute(int n,int m)
{
int b[30001],f;
for (int i=1;i<=n;i++) {q[i]=i;bb[i]=false;}//初始化每个学生都未曾出现。队列初始化
for (int i=1;i<=m;i++)
{
cin >> f;
for (int j=1;j<=f;j++)
{
cin >> b[j];
bb[b[j]]=true;
}
for (int j=2;j<=f;j++)
{
jiehe(b[1],b[j]);//作连通图
}
}
int d=0;
for (int i=0;i<=n;i++)
if (bb[i]&&find(i)==q[0]) d++;//只有出现过的学生并且找到父亲节点与0号学生相同,计数
cout << d << endl;
}
int main()
{
int n,m;
cin >> n >> m;
while(n!=0||m!=0)
{
solute(n,m);
cin >> n >> m;
}
}