Dragon Balls HDU - 3635(并查集)

题目链接
题目描述:第i个龙珠在第i个城市,如果是T a b,就是a城市往b城市移动,如果是Q a就是输出a在哪个城市,接着输出该城市持有的龙珠数量,还有a移动时间。
思路:
1)a所在城市即在求a的父节点;还有就是每个城市未移动之前时间都是0、个数都是自己本身一个、每个点的父节点都为自己本身。
2)所以在执行上面操作时需要先找a,b各自的父节点。
在找父节点时,如果x!=p[x]了,说明x之前有移动到p[x]这个城市,那么x的移动时间得加上p[x]的移动时间。
找完后a,b的父节点后(设找到的父节点仍为a,b),这时b就成了a的父节点,那么b持有的龙珠数量得加上a本身的龙珠数,同时也要记录a的移动时间。
代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int p[200005],time[200005],sum[200005],X;
int Find(int x)
{
    if(x!=p[x])
    {
        int l=p[x];
        p[x]=Find(p[x]);
        time[x]+=time[l];//由于x!=p[x]了,也就是x曾经移动到p[x]那,x的移动时间得加上p[x]的时间
        return p[x];
    }
    return x;
}
void Union(int x,int y)
{
    x=Find(x);
    y=Find(y);
    if(x!=y)
    {
        p[x]=y;
        sum[y]+=sum[x];//x移到y,那么y得加上x的那一份
        time[x]++;
        //x移动了得记录
    }else return;//如果相等要返回
}
int main()
{
    int t,n,k,a,b;
    char s[5];
    scanf("%d",&t);
    for(int j=1; j<=t; j++)
    {
        scanf("%d%d",&n,&k);
        for(int i=1; i<=n; i++)//**这应该从1开始 **
        {
            p[i]=i;
            sum[i]=1;
            time[i]=0;
        }
        printf("Case %d:\n",j);
        for(int i=0; i<k; i++)
        {
            scanf("%s",&s);
            if(s[0]=='T')
            {
                scanf("%d%d",&a,&b);
                Union(a,b);
            }
            else
            {
                scanf("%d",&a);
                X=Find(a);//**找a的父节点**
                printf("%d %d %d\n",X,sum[X],time[a]);
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值