hdu 2818

题意:

有N块转, 有两种操作。

M x y:把x所在的砖堆放在y所在的砖堆上 

C x:输出砖x下面的砖的数量

这种一堆,一堆的很明显是并查集,不过带权。

那么我们需要考虑,合并时,把x的根作为父节点还是y的根作为父节点。因为是输出每一块砖下面的砖的数量,所以,我们应该以下面为父节点,因为我们需要更新的是上面的砖,而下面的砖的状态是不变的。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 30000 + 5;
const int maxp = 1000000 + 5;
int par[maxn];
int num[maxn];//num表示当把砖i压在下面时,上面的砖需要加上num[i]。也就是堆i的总砖数。
int cnt[maxn];//cnt表示有cnt[i]砖在砖i的下满。
void init()
{
    memset(cnt, 0, sizeof(cnt));
    for(int i = 0; i < maxn; i++)
    {
        par[i] = i;
        num[i] = 1;
    }
}
int root(int x)
{
    if(x != par[x])
    {
        int t = root(par[x]);
        cnt[x] += cnt[par[x]];
        par[x] = t;
    }
    return par[x];
}
bool same(int x, int y)
{
    return root(x) == root(y);
}
void unite(int x, int y)
{
    int fx = root(x);
    int fy = root(y);
    par[fx] = fy;
    cnt[fx] = num[fy];//把堆fy压在下面。
    num[fy] += num[fx];//他们是一堆了,而根节点是fy。
}
int main()
{
    int p;
    while(scanf("%d", &p) == 1)
    {
        init();
        for(int i = 0; i < p; i++)
        {
            char cmd;
            cin>>cmd;
            if(cmd == 'M')
            {
                int s1, s2;
                scanf("%d%d", &s1, &s2);
                if(!same(s1, s2))
                {
                    unite(s1, s2);
                }
            }
            else
            {
                int s;
                scanf("%d", &s);
                root(s);
                printf("%d\n", cnt[s]);
            }
        }
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章