并查集初步

题目:HDU 1213

题意就是有一群人要去吃饭,但是不认识的不能坐在一起,这就要我们将认识的人合并……

赤裸裸的并查集。但是开始有个天真的想法:

用一个set数组记录,每次将有关系的人的值变为前一个人的值。

然后仔细想一想明显是不行的……

比如这个数据:1 - 2 , 3 - 4 , 2 - 3

对于4个人的这个数据显然只需要一张桌子!因为都认识。。。。可是如果用上面的方法将会得到错误的答案!

所以只能用并查集了~~

不说了,贴代码+注释:

#include <cstdio>
#include <algorithm>

int set[1050];

int find(int x)
{
    int t = x;
    while (t != set[t]) t = set[t];
    return t;
}

void Union(int x , int y)
{
     int a = find(x);
     int b = find(y);
     set[a] = b;
}

int main()
{
    int T , n , m , a , b;
    int i , ans;
    
    scanf("%d" , &T);
    while (T --)
    {
         scanf("%d%d" , &n , &m);
         for (i = 1 ; i <= n ; i ++)
            set[i] = i;
         ans = 0;
         for (i = 0 ; i < m ; i ++)
         {
             scanf("%d%d" , &a , &b);
             if (find(a) != find(b))  // 看看是否属于同一个集合
             {
                 ans ++;  // 若不是则ans + 1
                 Union(a , b);   // 合并起来
             }
         }
         printf("%d\n" , n - ans);
    }
}

对于数据:

1

4 3

1 2

3 4

2 3

得到的树是这个样子的:

转载于:https://www.cnblogs.com/hmhard/archive/2013/02/26/2933960.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值