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;
}


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