How Many Tables(并查集)HDU - 1213

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

题意:今天是伊格纳修斯的生日。他邀请了很多朋友。现在是吃晚饭的时候了。伊格纳修斯想知道他至少需要几张桌子。你必须注意到不是所有的朋友都认识对方,所有的朋友都不想和陌生人呆在一起。
这个问题的一个重要规则是,如果我告诉你A知道B,B知道C,这意味着A,B,C互相了解,所以他们可以呆在一张桌子上。
例如:如果我告诉你A知道B,B知道C,D知道E,那么A,B,C可以放在一张桌子上,D,E必须放在另一张桌子上。所以伊格纳修斯至少需要两张桌子。

//看了一位大佬的博客,秒懂并查集,初学可以去看看,写的太好了
//附地址:https://blog.csdn.net/niushuai666/article/details/6662911
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include <sstream>
#include<vector>
#include<cmath>    
#include<stack>
#include<time.h>
#include<ctime>
using namespace std;
#define inf 1<<30
#define eps 1e-7
#define LD long double
#define LL long long
#define maxn 100000005
int pre[1009] = {};
int rootsearch(int root)//寻找这个数的领导
{
    int son;
    son = root;
    while (root != pre[root])//这个数不是领导,继续往下找
    {
        root = pre[root];
    }
    while (son != root)//路径压缩,把找到的下级数全部指向最高领导
    {
        int temp = pre[son];
        pre[son] = root;
        son = temp;
    }
    return root;//返回最高领导
}
int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        memset(pre, 0, sizeof(pre));
        int n, m, total;
        scanf("%d%d", &n, &m);
        total = n;//n个集合
        for (int i = 1; i <= n; i++)//一开始,自己是自己的领导
        {
            pre[i] = i;
        }
        while (m--)
        {
            int x, y;
            int root1, root2;
            scanf("%d%d", &x, &y);
            root1 = rootsearch(x);
            root2 = rootsearch(y);
            if (root1 != root2)//两个人的最高领导不同
            {
                pre[root1] = root2;//把第一个集合的最高领导改为第二个集合的最高领导
                total--;//集合数减一
            }
        }
        printf("%d\n", total);
    }
    return 0;
}

 

posted @ 2020-06-03 01:13  夜灯长明  阅读(151)  评论(0编辑  收藏  举报