POJ1988(带权并查集,搬砖块)

题意:
       可以这样理解,有n快方形积木,一开始都是单独的放到哪,然后有两种操作
1 M a b 把a所在的那一堆落到b所在那一堆的上面(一开始自己是一堆)
2 C a 问a下面有多少个积木


思路: 
       感觉很久以前杭电上见过这个题目,比较简单的带权并查集,我们可以维护两个权来满足要求,第一个就是记录集合元素个数,就是合并的时候更新a所在的祖宗节点的距离权值,第二个权值就是距离权值,记录每个元素距离根节点的距离,然后更新就是简单更新没啥说的,还有就是简简单单敲完提交后WA了一发,哎!丢脸,还好不是比赛,让我想起了有一场亚洲赛的水题我果断敲完,然后上去1WA。这个题目我WA是因为忘记了输出距离权值前要先查询一下,也就是更新一下,因为用了路径压缩,路径压缩的最理想状态是一个点,四周连着所有本集合的其他点,但是要想把一个路径上压缩成一对多,起码要查询就是更新一便,因为在动态的更新的时候当前所有状态并是不理想路径压缩后的状态,这个自己画画很容易理解,哎!记得当时还经常给小学弟讲这个问题呢!。


#include<stdio.h>


#define N 30000 + 10


int mer[N] ,sum[N] ,s_x[N];


int Finds(int x)
{
    if(x == mer[x]) return x;
    int t = mer[x];
    mer[x] = Finds(mer[x]);
    s_x[x] += s_x[t];
    return mer[x];
}


int main ()
{
    int m ,i ,x ,y ,a ,b;
    char str[5];
    for(i = 1 ;i <= 30000 ;i ++)
    s_x[i] = 0 ,sum[i] = 1 ,mer[i] = i;
    scanf("%d" ,&m);
    for(i = 1 ;i <= m ;i ++)
    {
        scanf("%s" ,str);
        if(str[0] == 'M')
        {
            scanf("%d %d" ,&a ,&b);
            x = Finds(a);
            y = Finds(b);
            s_x[x] = sum[y];
            sum[y] += sum[x];
            mer[x] = y;
        }
        else
        {
            scanf("%d" ,&a);
            Finds(a);
            printf("%d " ,s_x[a]);
        }
    }
    return 0;
}





原文地址:https://www.cnblogs.com/csnd/p/12062482.html