poj 1988 多校联赛 带权并查集

  这个题的意思是初始给你N个砖块, 维护两个操作, M a, b表示将含有a的堆放到b堆得上面(a和b在同一堆得话那么就忽略此操作, 有种并查集的感觉), C a查询a下面有几个砖块, 其实我们可以使用带权的并查集来维护这个题, 增加两个变量under[i]表示i下面有几个装快, cnt[i]表示以i为底的堆有几个砖块, 然后我们就可以在并查集Find函数回溯的时候就可以更新under数组。。 代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn = 30000 + 100;
int par[maxn];
int cnt[maxn], under[maxn];

void init(int n)
{
    for(int i=1; i<=n; i++)
    {
        par[i] = i;
        cnt[i] = 1;
        under[i] = 0;
    }
}

int Find(int x)
{
    if(x == par[x]) return x;
    else
    {
        int t = Find(par[x]);
        under[x] += under[par[x]];    //加过之后 路径压缩
        return par[x]=t;
    }
}

void Union(int x, int y)
{
    x = Find(x); y = Find(y);
    if(x != y)    //x摞在y上
    {
        under[x] = cnt[y];
        cnt[y] += cnt[x];
        par[x] = y;
    }
}

char s[10];

int main()
{
    int N;
    while(scanf("%d", &N) != EOF)
    {
        init(30000);
        for(int i=0; i<N; i++)
        {
            scanf("%s", s);
            if(s[0] == 'M')
            {
                int a, b;
                scanf("%d%d", &a, &b);
                Union(a, b);
            }
            else
            {
                int a;
                scanf("%d", &a);
                Find(a);
                printf("%d\n", under[a]);
            }
        }
    }
    return 0;
}

 

posted @ 2016-03-12 10:09  xing-xing  阅读(141)  评论(0编辑  收藏  举报