1. 程式人生 > >POJ - 1988:並查集(帶權)

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