HDU - 1213 How Many Tables【并查集】

How Many Tables

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 49429 Accepted Submission(s): 24579

Problem Description
Today is Ignatius’ birthday. He invites a lot of friends. Now it’s dinner time. Ignatius wants to know how many tables he needs at least. You have to notice that not all the friends know each other, and all the friends do not want to stay with strangers.

One important rule for this problem is that if I tell you A knows B, and B knows C, that means A, B, C know each other, so they can stay in one table.

For example: If I tell you A knows B, B knows C, and D knows E, so A, B, C can stay in one table, and D, E have to stay in the other one. So Ignatius needs 2 tables at least.

Input
The input starts with an integer T(1<=T<=25) which indicate the number of test cases. Then T test cases follow. Each test case starts with two integers N and M(1<=N,M<=1000). N indicates the number of friends, the friends are marked from 1 to N. Then M lines follow. Each line consists of two integers A and B(A!=B), that means friend A and friend B know each other. There will be a blank line between two cases.

Output
For each test case, just output how many tables Ignatius needs at least. Do NOT print any blanks.

Sample Input
2
5 3
1 2
2 3
4 5

5 1
2 5

Sample Output
2
4

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1213

简述:n表示有多少个人,m表示有几组朋友。如果a跟b在一组,表示他们相互认识可以在一桌,如果b跟c也认识,则a、b、c可以在一桌。

扫描二维码关注公众号,回复: 5392780 查看本文章

分析:用一个数组来储存每个人对应的号码,如果两个人相互认识,则修改其中一个人的数组内容,使之与父节点相同,当这个人同时被第三个人认识时,再次修改第三个人的数组内容,使之与父节点相同。

说明:一开始没有写find函数,跟题目给出的测试结果是相同的,结果WA,后来认真想了想,当出现了另一种比如a跟b认识,a跟c认识的时候就会出错,才有点明白find函数回溯的作用。

AC代码如下:

#include <iostream>
#include <cstring>
using namespace std;
int a[1010];
int find(int d)
{
	if (d != a[d]) a[d] = find(a[d]); //如果数组对应的值已经被修改了,那么回溯到它的父节点。
	return a[d];
}
int hebing(int q, int w)
{
	return a[q] = w;
}
int main()
{
	int t, k;
	cin >> t;
	while (t--)
	{
		k = 0;
		int n, m, i, q, w;
		cin >> n >> m;
		for (i = 1; i <= n; i++)
		{
			a[i] = i;
		}
		for (i = 0; i < m; i++)
		{
			cin >> q >> w;
			q = find(q);
			w = find(w);
			if (q != w) hebing(q, w);
		}
		for (i = 1; i <= n; i++)
		{
			if (a[i] == i) k++;
		}
		cout << k << endl;
	}
}
#include <iostream>
using namespace std;
int map[1010];
int find(int a) {	
	if (map[a] != a) map[a] = find(map[a]);	//这里修改值
	return map[a];
}
int main()
{
	int T, n, m, a, b, i, q, w, k;
	cin >> T;
	while (T--) {
		k = 0;
		cin >> n >> m;
		for (i = 1; i <= n; i++)
			map[i] = i;
		while (m--) {
			cin >> a >> b;
			q = find(a);
			w = find(b);
			if (q != w) map[q] = w;
		}
		for (i = 1; i <= n; i++)
			if (map[i] == i) k++;
		cout << k << endl;
	}
}

猜你喜欢

转载自blog.csdn.net/qq_43966202/article/details/86700131