HDU 3635 Dragon Balls(并查集--路径压缩拓展应用)

题目大意:
初始时,有n个龙珠,编号从1到n,分别对应的放在编号从1到n的城市中。
现在又2种操作:
T A B,表示把A球所在城市全部的龙珠全部转移到B城市。(第一次时,因为A球所在的城市只有一个球,所以只移动1个,如果有多个,则全部移动)。

Q A,表示查询A。要求得到的信息分别是:A现在所在的城市,A所在城市的龙珠数目,A转移到该城市移动的次数(如果没有移动就输出0)

思路:并查集,难点在于求龙珠的转移次数,可以在路径压缩的过程中沿着递归路径累加。

//Accepted	1740 KB	530 ms	
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1e4+1e2;
struct node
{
    int cnt;
    int fa;
}ball[N];
int num[N];
int n,q;
void ini()
{
    for(int i=1;i<=n;i++)
    {
        num[i]=1;
        ball[i].fa=i;
        ball[i].cnt=0;
    }
}
int getf(int v)
{
    if(v==ball[v].fa) return v;
    int tmp=ball[v].fa;
    ball[v].fa=getf(ball[v].fa);
    ball[v].cnt+=ball[tmp ].cnt;
    return ball[v].fa;
}
void Merge(int x,int y)
{
    int t1=getf(x);
    int t2=getf(y);
    ball[t1].fa=t2;
    ball[t1].cnt++;
    num[t2]+=num[t1];
}
int main()
{
    int T;
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++)
    {
        printf("Case %d:\n",cas);
        scanf("%d%d",&n,&q);
        ini();
        while(q--)
        {
            char op[5];
            scanf("%s",op);
            if(op[0]=='T')
            {
                int a,b;
                scanf("%d%d",&a,&b);
                Merge(a,b);
            }
            else
            {
                int p;
                scanf("%d",&p);
                int city=getf(p);
                printf("%d %d %d\n",city,num[city],ball[p].cnt);
            }
        }
    }
    return 0;
}


你可能感兴趣的:(HDU 3635 Dragon Balls(并查集--路径压缩拓展应用))