POJ - 1988:并查集(带权)

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int par[int(3e4 + 5)] , cnt[int(3e4 + 5)] , dis[int(3e4 + 5)];
//cnt[i]表示i所在点的大小,dis[i]表示i离最上面节点的距离(个数)
int Find(int n) {
    if(par[n] == n)  return n;
    int temp = Find(par[n]); //先算出n的父节点的dis
    cout<<"temp:"<<temp<<" par["<<n<<"]:"<<par[n]<<endl;
    dis[n] += dis[par[n]];
    cout<<"dis["<<n<<"]:"<<dis[n]<<endl;
    par[n] = temp; //路径压缩
    cout<<"par["<<n<<"]:"<<par[n]<<endl;
    return temp;
}

void Union(int u , int v) {
    int fu = Find(u) , fv = Find(v);
    if(fu == fv)
        return ;
cout<<"fu:"<<fu<<" fv:"<<fv<<endl;
    par[fv] = fu;
cout<<"par["<<fv<<"]"<<par[fv]<<endl;
    dis[fv] = cnt[fu]; //Find函数中dis[fv]并没有回溯增加过
cout<<"cnt["<<fu<<"]"<<cnt[fu]<<" dis["<<fv<<"]"<<dis[fv]<<endl;
    cnt[fu] += cnt[fv]; //总个数相加
cout<<"cnt["<<fu<<"]"<<cnt[fu]<<endl;
}

int main()
{
    int n , u , v;
    char q[3];
    while(cin>>n) {
        memset(dis , 0 , sizeof(dis));
        for(int i = 1 ; i <= 3e4 ; ++i) {
            cnt[i] = 1;
            par[i] = i;
        }
        for(int i = 0 ; i < n ; ++i) {
            cin>>q;
            if(q[0] == 'M') {
                cin>>u>>v;
                Union(u , v);
            }
            else {
                cin>>u;
                int x = Find(u); //回溯累加一次
               cout<< "cnt["<<x<<"]-dis["<<u<<"]-1:"<<cnt[x] - dis[u] - 1<<endl;
            }
        }
    }
    return 0;
}
//

转载自https://blog.csdn.net/Tribleave/article/details/72878239

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值