Question C: COVID-19

Question C: COVID-19

Topic description: In
2020, new coronary pneumonia will sweep the world.
China adopts the policy of never giving up, always puts the safety of the people's lives in the first place, and resolutely defends the right to life of every citizen, which has won praise from all over the world.
In the working standards of epidemiological investigations (hereinafter referred to as "fluid investigation") conducted in Mainland China, close contacts of cases (hereinafter referred to as "close contacts") need to be traced, and isolation and screening work should be carried out.

Insert picture description here
The Nanjing case is a tutoring class teacher, so the students in the basketball tutoring class of the English tutoring class he has taught and the people they contact must be investigated.
It is known that there are n student clubs in a certain university. Due to the frequent exchange of activities and activities of the student clubs, once one person is infected with the virus, everyone in the club and everyone in the club they participate in may be infected, so these people will be infected. Isolation and testing.
We are accustomed to call the first infected person as patient 0. Please find out how many students will be quarantined in the end after a school with No. 0 infected person.

Input
Input contains multiple sets of test cases. For each test case, the first line contains two integers n and m, where n represents the number of students in the school, and m represents the number of clubs. Assume that 0 <n ≤ 30000 and 0 ≤ m ≤ 1000. Each student is numbered from 0 to n-1. Next are m lines. At the beginning of each line is an integer k indicating the number of students in the club, and then k integers indicating the student number of the club. The last test case, n = 0, m = 0, indicates the end of the input.
Output
Corresponding to each group of data, output one line, including an integer, indicating the number of students who were infected with the virus after the 0th student was infected.

Sample input
10 2
3 0 1 2
5 2 4 5 6 7

120 5
5 8 12 13 17 20
2 4 6
3 0 2 4
2 99 2
8 0 4 8 10 12 13 14 15

1 0

0 0

Sample output
7
13
1

Prompt
: In the first group of samples, 10 students and 2 clubs were infected with 0 1 2, and No. 2 was infected with 4 5 6 7. Therefore, a total of 0 1 2 4 5 6 7 and a total of 7 people were quarantined.

For this problem, the author gives the following two ideas for solving the problem. (This time we update the idea and code of
Method One ) Method One: Regard each student as an element in the set, and merge the students in the same club by using the union search set. After all the merging is completed, find the root node of the student with number 0 through the Find() function, and output the Num[] of the root node of the student with number 0. (Here is a one-off, see code 1 for specific operations).

#include <stdio.h>

#define MAX 30001//学校学生人数n最多为30000。

int parent[MAX];//定义一个全局数组parent[],用来记录每个元素的根结点。
int Num[MAX];//定义一个全局数组Num[],用来记录根结点所在集合的元素个数。

/*初始化操作*/
void init(int n)
{
    
    
	int i;
	for(i=0;i<n;i++)
	{
    
    
		parent[i]=i;//将每个结点的父结点设置成自己(学生从0——n-1编号)。
		Num[i]=1;//将每个结点所在集合的元素个数设置为1。
	}
} 

/*查询元素的根结点操作*/
int Find(int i)
{
    
    
	if(parent[i]==i)//如果该元素的父结点就是其自己,则说明该元素为根结点,返回该元素的编号。
	 return i;
	else
	/*否则递归地去寻找该元素的根结点,
	递归操作顺便把从根到该结点路径上的所有结点都直接放到根节点下。*/
	 return parent[i]=Find(parent[i]);//压缩路径。
	 //补充:压缩路径的好处:有可能降低了树高,提高以后的查询效率。
}

/*集合合并操作*/
/*找到元素a的根结点A,元素b的根结点B,
如果元素a与元素b的根结点不同,则将A的父结点设置为B,并且更新以B为根结点的集合元素个数。*/
void Union(int a,int b)
{
    
    
	int A=Find(a);
	int B=Find(b);
    if(A!=B)
    {
    
    
    	parent[A]=B;
    	Num[B]+=Num[A];
	}
}

int main(int argc, char *argv[]) {
    
    
	int n,m,i,j,k,x,y;
	scanf("%d%d",&n,&m);//输入学校学生人数n和社团个数m。
	while(n!=0||m!=0)//输入结束条件n=0,m=0。
  {
    
     
    i=1;//初始化i为1.
    init(n);//对n个集合进行初始化(学生编号0——n-1,一开始将每个学生看成互不相交的单元素集合)
    
	while(i<=m)//m个社团。
	{
    
    
		scanf("%d%d",&k,&x);//输入社团人数k,和该社团中的第一个学生编号x。
		for(j=1;j<k;j++)//剩下k-1个该社团的学生,所以进行k-1次循环。
		{
    
    
			scanf("%d",&y);//输入该社团中的一个学生编号。
			Union(x,y);//将该生与第一个学生所在的集合进行合并操作。
		}
		i++;
	}
	int zero_root=Find(0);//找到编号为0的学生的根结点
	
	/*如果输入的社团个数为0,则输出1。
	举例:如果学校学生人数为1000,0个社团,0号学生感染了,则最后染病的学生人数为1。*/
	if(m==0)
	 printf("1");
	else//否则,输出编号为0的学生的根结点所在集合的个数。
	 printf("%d\n",Num[zero_root]);
	
	scanf("%d%d",&n,&m);
  }
  	return 0;
}

The above is the idea and code of the first method, and the second solution will be updated next time. Friends, if you have better ideas, questions, and suggestions for solving problems, you can tell me in the comment area. That's all for this sharing, thank you all for watching.

Guess you like

Origin blog.csdn.net/qq_46139801/article/details/113184509