Week6: wear a mask! - disjoint-set

Title Description
novel coronavirus pneumonia (Corona Virus Disease 2019, COVID- 19), referred to as "the new crown pneumonia" refers to the 2019 novel coronavirus infection caused by pneumonia.
If an infected person into a group, then this group need to be isolated!
A small student was diagnosed with the new crown infection, and does not wear a mask! ! ! ! ! !
Risk! ! !
Time is running out! ! ! !
Need to find as quickly as possible to all students and small A direct or indirect contact through the students, they will be isolated to prevent the spread of a wider range.
As we all know, students' communication may be in small groups, a student may also participate in multiple small groups.
Please write a program to solve! wear mask! !

Input format
multiple sets of data, for each test:
the first two integers n and Behavior m (n = m = 0 indicates the end of input, does not need to process), n is the number of students, m is the number of groups of students. 0 <n <= 3e4, 0 <= m <= 5e2
student number of 0 ~ n-1
A small number 0.
Then, m lines, each person has a number of small groups i.e. integer num. Followed by a num integer representing students in small groups.

Output format
number to output isolation, the answer is the output of each data per line

Enter Case

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 Case

4
1
1

Analysis of ideas
in fact now there is no school, so this question does not exist (escape

In fact, you can quickly go over the topic found that this is a disjoint-set.
Personally I prefer the disjoint-set dubbed the "father looking set", because the entire process is to find every point of the "Leader", all have the same "Leader" is a community.

So the idea is very clear, that is, input data, looking for the father thing.
To avoid timeouts, remember to use route optimization, from father to find more rapid (bushi)

#include <iostream>
#include <vector>
#include <cstring>

using namespace std;

int father[30002];
int rnk[30002];

int findfather(int x)//找爹
{
	if (x == father[x]) return x;
	else return father[x] = findfather(father[x]);//优化路径
}

void Union(int a, int b)//认爹
{
	a = findfather(a);
	b = findfather(b);
	if (a == b) return;

	/*if (rnk[a] > rnk[b]) father[b] = a, rnk[a] = (rnk[b] += rnk[a]);
	else father[a] = b, rnk[b] = (rnk[a] += rnk[b]);*/
	//上面是用来维护生成树的秩的

	father[b] = a;
}

int main()
{
	int n, m;
	while (cin >> n >> m)
	{
		if (n == 0 && m == 0) break;

		for (int i = 0; i < n; i++)
		{
			father[i] = i;
			rnk[i] = 1;
		}

		int num, j1, jx;
		for (int i = 0; i < m; i++)
		{
			cin >> num;
			for (int j = 0; j < num; j++)
			{
				if (j == 0)
				{
					cin >> j1;
					continue;
				}
				else
				{
					cin >> jx;
					Union(j1, jx);
				}
			}
		}

		for (int i = 0; i < n; i++)
		{
			father[i] = findfather(i);
		}

		int t = father[0];
		int ans = 0;
		for (int i = 0; i < n; i++)
		{
			if (father[i] == t) ans++;
		}

		cout << ans << endl;

	}
}

Published 21 original articles · won praise 3 · Views 403

Guess you like

Origin blog.csdn.net/qq_44506233/article/details/105282571