Dragon Balls(hdu3635带权并查集)

题意:n个城市有n个龙珠,T  a,b 代表将龙珠a移动到b城市,Q a代表查询龙珠a所在城市,该城市有多少颗龙珠,该龙珠移动了多少次。

注意:移动时是将龙珠所在该城市所有龙珠都移动,每个龙珠不会再回到自己以前呆过的城市。就是说假如龙珠1,2,3,都在城市2,那么龙珠就不能再移动了

在路径压缩的时候更新他的距离值


rootxx --> rootx 移动是3,rootx -->x的移动是5 那么 rootxx --> x的移动就是rootxx --> rootx+rootx -->x =  3 + 5 = 8

所以还是向量

在find操作的时候

 int temp = p[x].father;
        p[x].father = Find_set(p[x].father);
        p[x].trap += p[temp].trap;


先保存他以前父亲的节点,然后更新时将他自己的节点和他原父亲的节点运输次数相加。

这样一层一层更新就可以了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct bian
{
    int sum;
    int father;
    int trap;
}p[10005];

void Make_set(int n)
{
    int i;
    for(i = 1; i <= n; i++)
    {
        p[i].sum = 1;
        p[i].father = i;
        p[i].trap = 0;
    }
}

int Find_set(int x)
{
    if(x != p[x].father)
    {
        int temp = p[x].father;
        p[x].father = Find_set(p[x].father);
        p[x].trap += p[temp].trap;
    }
    return p[x].father;
}

void Union(int a,int b)
{
    int x = Find_set(a);
    int y = Find_set(b);

    if(x == y)
        return ;
    else
    {
        p[x].father = y;
        p[x].trap++;
        p[y].sum += p[x].sum;
    }
}
int main()
{
    int t,cas = 1;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        int i;
        Make_set(n);printf("Case %d:
",cas++);
        for(i = 0; i < m; i++)
        {
            char c[5];
            int a,b;
            scanf("%s",c);
            if(c[0] == 'T')
            {
                scanf("%d%d",&a,&b);
                Union(a,b);
            }
            else
            {
                scanf("%d",&a);
                int temp = Find_set(a);                
                printf("%d %d %d
",temp,p[temp].sum,p[a].trap);
            }
        }
    }
    return 0;
}


原文地址:https://www.cnblogs.com/jiangu66/p/3217590.html