hdu 3635 Dragon Balls

一个城市有一个龙珠,每次两个操作,第一个操作把一个城市的龙珠移到另一个城市。

第二个操作询问第i个龙珠在哪个城市以及那个城市的size以及这个龙珠的转移次数。

用并查集维护一个联通块的size以及一个转换次数cnt。

每次合并联通块的时候把根节点的cnt++,然后在find的时候做压缩路径以及字节点cnt的更新。

 

 

#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define x first
#define y second
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define up rt,rt<<1,rt<<1|1
#define mem(x) memset(x,0,sizeof(x))
#define mem1(x) memset(x,-1,sizeof(x))
#define LMissher
using namespace std;
typedef long long ll;
typedef double db;
const int M = 1e4+7;
const double pi = acos(-1);
const int inf = 2147483647;
const int mod = 1e9+7;

int _,n,q,cas=1;
int f[M],sz[M],cnt[M];
//维护联通块大小及转换次数
void init(){
    for(int i=1;i<=n;i++) f[i]=i,sz[i]=1,cnt[i]=0;
}
int find(int x){//路径压缩以及子节点的转换次数更新
    if(x==f[x]) return x;
    int tmp=f[x];
    f[x]=find(f[x]);
    cnt[x]+=cnt[tmp];
    return f[x];
}
int main(){
    #ifdef LMissher
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    scanf("%d",&_);
    while(_--){
        printf("Case %d:\n",cas++);
        scanf("%d%d",&n,&q);
        init();
        char op[2];int x,y;
        while(q--){
            scanf("%s",op);
            if(op[0]=='T'){
                scanf("%d%d",&x,&y);
                int fx=find(x),fy=find(y);
                if(fx!=fy){
                    sz[fy]+=sz[fx];
                    cnt[fx]++;//根节点的转换次数+1
                    f[fx]=fy;
                }
            }
            else{
                scanf("%d",&x);
                int fx=find(x);
                printf("%d %d %d\n",fx,sz[fx],cnt[x]);
            }
        }
    }
    return 0;
}
View Code

 

posted @ 2018-09-11 13:48  LMissher  阅读(137)  评论(0)    收藏  举报