POJ 1611 The Suspects (with weighted and searched entry template questions) (detailed)

topic link

Topic description

Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown cause, has been recognized as a global threat since mid-March 2003. To reduce the chance of transmission to others, the best strategy is to isolate possible patients.
At Not-Spreading-Your-Sickness University (NSYSU), there are many student groups. Students in the same group often communicate with each other, and a student can join several groups at the same time. To prevent the spread of SARS, NSYSU collected member lists of all student groups. Their standard operating procedure (SOP) is as follows:
once there is a possible patient in a group, all members of the group are possible patients.
However, they found that it was not easy to identify all possible patients when a student was identified as a possible patient. Your job is to write a program that finds all possible patients.

input format

The input file contains multiple sets of data.
For each set of test data:
the first row is two integers n and m, where n is the number of students and m is the number of groups. 0 < n <= 30000, 0 <= m <= 500.
Each student number is an integer between 0 and n-1, and initially only student number 0 is considered a possible patient.
This is followed by a list of members of the group, one row per group.
Each row has an integer k, which represents the number of members. After that, there are k integers representing this group of students. All integers on a line are separated by at least one space.
n = m = 0 means the input is over and no processing is required.

output format

For each set of test data, output a row of possible patients.

Input and output example

Enter #1

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

output #1

4
1
1

topic analysis

Knowing from the question: There are n students, numbered from 0 to n-1. Initially, student No. 0 is the patient. The final number of patients is the number of students in the team of student 0.
Because sets and numbers are involved, we will naturally think of using weighted union search to solve this problem.

First open an array of the number of records (denoted as num[maxn], all initially set to 1, which means that there is only one person in the team. Then each time you merge, the number in the new team is equal to the number in the two merged teams. Add(num[x] += num[y]). The final number of patients is num[Find(0)].

AC code:

(There is no comment in the function, see for details)

#include <stdio.h>
const int maxn = 3e4+10;
int f[maxn], h[maxn], num[maxn], n, m, k, x, y;
void Init() {
    
    
	for(int i=0; i<n; i++) {
    
    
		f[i] = i;
		h[i] = 0;
		num[i] = 1;
	}
}
int Find(int i) {
    
    
	return f[i]==i ? f[i] : f[i]=Find(f[i]);
}
void merge(int a, int b) {
    
    
	int fa = Find(a);
	int fb = Find(b);
	if(fa != fb) {
    
    
		if(h[fa] < h[fb]) {
    
    
			f[fa] = fb;			 //把 a的根指向 b的根 
			num[fb] += num[fa];  //把 a所在团队的数目加到 b所在团队中 
		} else {
    
    
			f[fb] = fa;			 //把 b的根指向 a的根 
			num[fa] += num[fb];  //把 b所在团队的数目加到 a所在团队中 
			if(h[fa] == h[fb]) h[fa]++;
		}
	}
}

int main(void) {
    
    
	while(scanf("%d %d", &n, &m) != EOF) {
    
    
		if(n==0 && m==0) return 0;  //直到 n与 m同时为 0时,结束 
		Init();  //初始化 
		while(m--) {
    
    
			scanf("%d", &k);
			scanf("%d", &x);  //先输入第一个学生编号 
			for(int i=2; i<=k; i++) {
    
    
				scanf("%d", &y);  //输入接下来的学生编号 
				merge(x, y);  //使后来的学生都进入第一个学生所在的团队 
			}
		}
		printf("%d\n", num[Find(0)]);
		//找到编号为 0的初始学生的根节点 
		//其对应的数目即为所有患者的数目 
	}
}

Guess you like

Origin blog.csdn.net/weixin_51250927/article/details/113620822