POJ1988 Cube Stacking(並查集)

題目連接:http://poj.org/problem?id=1988node

題意:有n個元素,開始每一個元素各自在一個棧中,有兩種操做,將含有元素x的棧放在含有y的棧的頂端,合併爲一個棧。
第二種操做是詢問含有x元素下面有多少個元素。
思路:
並查集,把每一堆看做一個棧,堆的下方看做棧頂。由於當咱們知道棧中元素的總數,和某元素到「棧頂」的距離,
咱們就能知道這個元素下面有多少元素。合併操做的時候,始終使用在下面棧的根來作合併以後的根,這樣也就達到了棧中的根是棧中的「棧頂」元素的效果,咱們只需在每一個「棧頂」中記錄該棧中的元素總數便可。然而咱們還須要得知某元素到「棧頂」的距離,這樣咱們就須要記錄每一個元素到其父親的距離,把它到根上所通過的距離加起來,即爲它到「棧頂」的距離。這樣咱們就得出告終果。
 
這個圖是在合併的時候的關鍵部分 
另外,在進行Find()操做時,有一句 under[x] += under[t[x].parent];這句話就是在遞歸尋找根結點時,計算出每一個元素距離棧底(根)的距離。
  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<vector>
  6 #include<stack>
  7 #include<map>
  8 #include<set>
  9 #include<list>
 10 #include<queue>
 11 #include<string>
 12 #include<algorithm>
 13 #include<iomanip>
 14 using namespace std;
 15 
 16 struct node
 17 {
 18     int parent;
 19     int date;
 20 };
 21 
 22 int * total;
 23 int * under;
 24 
 25 class DisJoinSet
 26 {
 27 protected:
 28     int n;
 29     
 30     node * tree;
 31 public:
 32     DisJoinSet(int n);
 33     ~DisJoinSet();
 34     void Init();
 35     int Find(int x);
 36     void Union(int x,int y);
 37 };
 38 
 39 DisJoinSet::DisJoinSet(int n)
 40 {
 41     this->n = n;
 42     tree = new node[n+2];
 43     total = new int[n+2];
 44     under = new int[n+2];
 45     Init();
 46 }
 47 DisJoinSet::~DisJoinSet()
 48 {
 49     delete[] under;
 50     delete[] total;
 51     delete[] tree;
 52 }
 53 
 54 void DisJoinSet::Init()
 55 {
 56     for(int i = 1;i  <= n ;i ++)
 57     {
 58         tree[i].date  = i;
 59         tree[i].parent = i;
 60         total[i] = 1;
 61         under[i] = 0;
 62     }
 63 }
 64 int DisJoinSet::Find(int x)
 65 {
 66     //int temp = tree[x].parent;
 67     if(x != tree[x].parent)
 68     {
 69         int par = Find(tree[x].parent);
 70         under[x] += under[tree[x].parent];//把父親結點下面的個數加到本身頭上
 71         tree[x].parent = par;
 72         return tree[x].parent;
 73     }
 74     else
 75     {
 76         return x;
 77     }
 78 }
 79 
 80 void DisJoinSet::Union(int x,int y)
 81 {
 82     int pa = Find(x);
 83     int pb = Find(y);
 84     if(pa == pb)return ;
 85     else
 86     {
 87         tree[pa].parent = pb;//x的根變爲y的根  即把x所在的堆放在y所在的堆上面
 88         under[pa] = total[pb];//pa下的數量即原來y所在棧裏的元素total
 89         total[pb] += total[pa];//更新y的totoal
 90     }
 91 }
 92 
 93 int main()
 94 {
 95     int p;
 96     while(scanf("%d",&p) != EOF)
 97     {
 98         if(p == 0)break;
 99         DisJoinSet dis(p);
100         char s1[2];
101         for(int i = 0 ;i < p ;i++)
102         {
103             
104             int s2;
105             int s3;
106             scanf("%s",s1);
107             if(s1[0] == 'M')
108             {
109                 scanf("%d%d",&s2,&s3);
110                 int pa = dis.Find(s2);
111                 int pb = dis.Find(s3);
112                 if(pa != pb)
113                 {
114                     dis.Union(s2,s3);
115                 }
116             }
117             if(s1[0] == 'C')
118             {
119                 scanf("%d",&s2);
120                 dis.Find(s2);
121                 cout<<under[s2]<<endl;
122             }
123         }
124         dis.~DisJoinSet();
125     }
126     return 0;
127 }
View Code
相關文章
相關標籤/搜索