HDU - 1213 How Many Tables [并查集]

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.

InputThe 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.
OutputFor 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

题意:今天是Ignatius的生日,她邀请了一些朋友在她家吃晚饭,这些朋友只和自己认识的人坐在同一桌,比如A认识B,B认识C,那么A,B,C可以坐在一桌,现在问Ignatius的晚餐至少要准备几张桌子?
思路:用并查集求连通分量的个数

在使用并查集之前,我们先要了解并查集是个什么东西
顾名思义,并查集的核心是合并和查询;并查集类似我们数据结构中学过的树结构,在实际应用中更像是对森林的操作,每个集合代表了一棵树,查询指的是查询某个结点
属于哪颗树,然后根据题意确定树的合并条件,将一些树合并,得到想要的结果。

查询->find函数
find函数是用来做什么的呢?就拿这道题来说,它是用来查询某个人所属的朋友圈的,假如A认识B,B又认识C,find(C)就是找C在哪个朋友圈,我们把靠前的作为朋友圈的领头羊,也就是A,A就标志了一个朋友圈,所以find(C) = A;

合并
假如A认识B和C, A,B,C要坐在一桌,D认识E和F, D,E,F要坐在一桌这时再来一个条件:A认识D,那这两桌人就可以坐在一起了,这时只要把这两个领头羊连接在一起就完成了合并操作。

了解了并查集的作用,这道题也就迎刃而解啦~

AC代码:
还有一些细节在代码注释里
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1050;
int fa[maxn];  //朋友圈的领头羊们 
int T, N, M;
int u, v;   //u和v认识 
int Find(int u)  //找u所在朋友圈的领头羊 
{
    if(u == fa[u]) return fa[u];
    else return fa[u] = Find(fa[u]);
}
void adde(int u, int v)  //u和v是朋友 
{
    int x = Find(u);  //找x所在朋友圈的领头羊 
    int y = Find(v);  //找y所在朋友圈的领头羊  
    if(x != y) fa[x] = fa[y];  //假如目前x和y所在朋友圈还不一样,那就把两个领头羊合为一体 
}
int main ()
{
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &N, &M);
        for(int i = 1; i <= N; i++)
            fa[i] = i;   //刚开始每个人自己是一个小团体 
        for(int i = 1; i <= M; i++)
        {
            scanf("%d%d", &u, &v);
            adde(u, v);   //u和v所在朋友圈合并 
        }
        int ans = 0;  //领头羊的个数,也就是桌子数 
        for(int i = 1; i <= N; i++)
        {
            if(fa[i] == i) ans++;
        }
        printf("%d\n", ans);
    }
    return 0;
}


猜你喜欢

转载自www.cnblogs.com/jiaqi666/p/8983198.html