POJ - 1988:並查集(帶權)
阿新 • • 發佈:2018-11-14
#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; } //