HDU 3635 Dragon Balls(带权并查集)

这题的关键是如何统计转移的次数

根结点都是最多移动一次的,所以记录移动次数时把自己的加上父亲结点的就是移动总数了

这里要注意:更新移动次数时,一定要先更新父亲的,在更新自己的,即用递归从最顶层开始往下更新

                 我的方法是在调用find_root前先更新一下,再路径压缩。

 

网上看了有人写的,在查找父节点的时候同时更新的代码:

 

int find_root(int x){
    int fa;
    if(father[x]==x)
        return x;
    fa=find(father[x]);
    int tmp=father[x];
    trans[x]+=trans[tmp];
    father[x]=fa;
    return fa;
}
/*
trans表示的是从x转移到father[x]用的步数
我们更新要变成x转移到根节点,这里也就是s用的步数
就是要father[x]的trans更新完才能更新x的trans
*/


下面附上我的代码:

 

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <set>

using namespace std;
int father[10010];
int ranks[10010];  //表示以i为根节点的集合中所含有的个数
int trans[10010];  //trans[i]表示i所移动的次数
int n,q;

void init(){
    for(int i=0;i<=n;i++){
        father[i]=i;
        ranks[i]=1;
    }
}

//x的父节点更新完相应的trans后,才能更新x的trans
int update(int x){
    if(father[x]==x)
        return trans[x];
    else{
        trans[x]+=update(father[x]);
        return trans[x];
    }
}
int find_root(int x){
    /*一开始更新trans的方法写在这里,结果WA。
      后来发现:
      如果写在这里,在第一次find_root时就能更新完全,
      但是接下来还会调用find_root方法,父节点又会再更新一遍,等于多加了几次
      改了一下,每次在调用find_root方法前,调用update()方法,AC

    */
    //trans[x]+=update(father[x]);
    if(father[x]!=x){
        father[x]=find_root(father[x]);
    }
    return father[x];
}

void Union(int a,int b){

    trans[a]+=update(father[a]);
    trans[b]+=update(father[b]);
    int x=find_root(a);
    int y=find_root(b);
    if(x==y)
        return;
    //是trans[x]++,一开始写了trans[a]++。。。
    trans[x]++;
    father[x]=y;
    ranks[y]+=ranks[x];

}

int main()
{
    int t,a,b,x,y,z;
    char ch[4];
    scanf("%d",&t);
    for(int i=1;i<=t;i++){
        memset(trans,0,sizeof(trans));
        printf("Case %d:\n",i);
        scanf("%d%d",&n,&q);
        init();
        for(int i=1;i<=q;i++){
            scanf("%s",ch);
            if(ch[0]=='T'){
                scanf("%d%d",&a,&b);
                Union(a,b);
            }
            else{
                scanf("%d",&a);
                trans[a]+=update(father[a]);
                x=find_root(a);
                y=ranks[x];
                z=trans[a];
                printf("%d %d %d\n",x,y,z);
            }
        }
    }
    return 0;
}

 

 

posted @ 2013-08-29 16:07  辰曦~文若  阅读(157)  评论(0编辑  收藏  举报