题目要求
新型冠状病毒肺炎(Corona Virus Disease 2019,COVID-19),简称“新冠肺炎”,是指2019新型冠状病毒感染导致的肺炎。
如果一个感染者走入一个群体,那么这个群体需要被隔离!
小A同学被确诊为新冠感染,并且没有戴口罩!!!!!!
危!!!
时间紧迫!!!!
需要尽快找到所有和小A同学直接或者间接接触过的同学,将他们隔离,防止更大范围的扩散。
众所周知,学生的交际可能是分小团体的,一位学生可能同时参与多个小团体内。
请你编写程序解决!戴口罩!!
Input
多组数据,对于每组测试数据:
第一行为两个整数n和m(n = m = 0表示输入结束,不需要处理),n是学生的数量,m是学生群体的数量。0 < n <= 3e4 , 0 <= m <= 5e2
学生编号为0~n-1
小A编号为0
随后,m行,每行有一个整数num即小团体人员数量。随后有num个整数代表这个小团体的学生。
Output
输出要隔离的人数,每组数据的答案输出占一行。
求解思路
使用并查集存储学生所在团体的信息,为了降低查找根节点的时间,查询根结点的函数如下:
int find(int x)
{
if (fa[x] == x)
return x;
return fa[x] = find(fa[x]);
}
每次查询,fa中的值都会被更新。
为了保证同一团体有且只有一个共同的根结点,合并函数如下:
void unio (int x, int y)
{
if (x > y)
swap(x, y);
if (x != y)
{
fa[y] = x;
ranked[x] = ranked[x] + ranked[y];
}
}
注意union是c++的关键字,不能使用。选取小的结点作为根节点,若x>y,使用swap函数将x,y交换。注意unio的参数是两个团体的根结点。
ranked数组记录团体中学生数量。
代码
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
int n, m;
int fa[30005];
int ranked[30005];
int find(int x)
{
if (fa[x] == x)
return x;
return fa[x] = find(fa[x]);
}
void unio (int x, int y)
{
if (x > y)
swap(x, y);
if (x != y)
{
fa[y] = x;
ranked[x] = ranked[x] + ranked[y];
}
}
int main()
{
while (1)
{
cin >>n>> m;
if (n == 0 && m == 0)
break;
for (int i = 0; i < n; i++)
{
fa[i] = i;
ranked[i] = 1;
}
for (int i = 0; i < m; i++)
{
int num;
cin >> num;
int first;
cin >> first;
for (int j = 1; j < num; j++)
{
int temp;
cin >> temp;
unio(find(first), find(temp));
}
}
cout << ranked[find(0)] << endl;
}
return 0;
}