題目連接:http://poj.org/problem?id=1703node
1 int DisJoinSet ::Find(int x) 2 { 3 int temp = tree[x].parent;//temp x的父親結點 4 if(x != tree[x].parent) 5 { 6 tree[x].parent = Find(tree[x].parent);//遞歸在雙親中找x 7 // tree[temp].relation必爲temp結點(x的父節點)與根節點的關係,tree[x].relation最初爲x與temp的關係, 8 // tree[x].relation == tree[temp].relation意味着tree[x].relation和tree[temp].relation同爲1,或者同爲0 9 // 若是tree[x].relation和tree[temp].relation同爲1,意味着根節點與temp不一樣類,temp與x不一樣類,總共只有2個集合,x與根節點一定同類。 10 // 若是tree[x].relation和tree[temp].relation同爲0,意味着根節點與temp同類,temp與x同類,x與根節點也一定同類。 11 if(tree[x].relation == tree[temp].relation) 12 { 13 tree[x].relation = 0; 14 } 15 // tree[x].relation != tree[temp].relation意味着tree[x].relation和tree[temp].relation一個爲1,一個爲0, 16 // 若是tree[temp].relation爲false,tree[temp].relation爲1,意味着根節點和temp同類,temp與x不一樣類,那麼x與根節點必然不一樣類 17 // 若是tree[temp].relation爲true,tree[x].relation爲0,意味着根節點和temp不一樣類,temp與x同類,那麼x與根節點必然不一樣類 18 else 19 { 20 tree[x].relation = 1; 21 } 22 return tree[x].parent;// 返回根節點下標 23 } 24 else 25 { 26 return x; 27 } 28 }
1 void DisJoinSet ::Union(int x,int y) 2 { 3 int rootx = Find(x); 4 int rooty = Find(y); 5 if(rootx == rooty) 6 { 7 return ; 8 } 9 if(tree[rootx].rank > tree[rooty].rank) 10 { 11 tree[rooty].parent = rootx; 12 // 此時rooty與其根結點rootx的關係如何肯定?由於Find方法也在進行路徑壓縮,x的父節點是rootx,y的父節點的rooty 13 // 若是tree[x].relation和tree[y].relation均爲1,說明x和rootx不一樣類,y和rooty不一樣類,而已知x和y不一樣類,所以rooty和rootx不一樣類; 14 // 若是tree[x].relation和tree[y].relation均爲0,說明x和rootx同類,y和rooty同類,而已知x和y不一樣類,所以rooty和rootx不一樣類 15 if(tree[x].relation == tree[y].relation) 16 { 17 tree[rooty].relation = 1; 18 } 19 // 若是tree[x].relation爲1,tree[y].relation爲0,說明x和rootx不一樣類,y和rooty同類,而已知x和y不一樣類,所以rooty和rootx必同類; 20 // 若是tree[x].relation爲0,tree[y].relation爲1,說明x和rootx同類,y和rooty不一樣類,而已知x和y不一樣類,所以rooty和rootx必同類; 21 else 22 { 23 tree[rooty].relation = 0; 24 } 25 } 26 else 27 { 28 tree[rootx].parent = rooty; 29 if(tree[rootx].rank == tree[rooty].rank) 30 { 31 tree[rooty].rank ++; 32 } 33 // 此時rooty與其根結點rootx的關係如何肯定?由於Find方法也在進行路徑壓縮,x的父節點是rootx,y的父節點的rooty 34 // 若是relation[x]和relation[y]均爲true,說明x和rootx不一樣類,y和rooty不一樣類,而已知x和y不一樣類,所以rooty和rootx不一樣類; 35 // 若是relation[x]和relation[y]均爲false,說明x和rootx同類,y和rooty同類,而已知x和y不一樣類,所以rooty和rootx不一樣類 36 if(tree[x].relation == tree[y].relation) 37 { 38 tree[rootx].relation = 1; 39 } 40 // 若是tree[x].relation爲1,tree[y].relation爲0,說明x和rootx不一樣類,y和rooty同類,而已知x和y不一樣類,所以rooty和rootx必同類; 41 // 若是tree[x].relation爲0,tree[y].relation爲1,說明x和rootx同類,y和rooty不一樣類,而已知x和y不一樣類,所以rooty和rootx必同類; 42 else 43 { 44 tree[rootx].relation = 0; 45 } 46 } 47 }
完整代碼:ios
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 no; 19 int rank; 20 int parent; 21 int relation; 22 }; 23 24 class DisJoinSet 25 { 26 protected: 27 int n; 28 node *tree; 29 public : 30 DisJoinSet(int n); 31 ~DisJoinSet(); 32 void Init(); 33 void Union(int x,int y); 34 int Find(int x); 35 bool itsSame(int x,int y); 36 }; 37 38 DisJoinSet ::DisJoinSet(int n) 39 { 40 this->n = n; 41 tree = new node[n+1]; 42 Init(); 43 } 44 45 DisJoinSet ::~DisJoinSet() 46 { 47 delete []tree; 48 } 49 50 void DisJoinSet::Init() 51 { 52 for(int i = 1; i <= n; i ++) 53 { 54 tree[i].no = i; 55 tree[i].rank = 0; 56 tree[i].parent = i; 57 tree[i].relation = 0; 58 } 59 } 60 61 int DisJoinSet ::Find(int x) 62 { 63 int temp = tree[x].parent;//temp x的父親結點 64 if(x != tree[x].parent) 65 { 66 tree[x].parent = Find(tree[x].parent);//遞歸在雙親中找x 67 // tree[temp].relation必爲temp結點(x的父節點)與根節點的關係,tree[x].relation最初爲x與temp的關係, 68 // tree[x].relation == tree[temp].relation意味着tree[x].relation和tree[temp].relation同爲1,或者同爲0 69 // 若是tree[x].relation和tree[temp].relation同爲1,意味着根節點與temp不一樣類,temp與x不一樣類,總共只有2個集合,x與根節點一定同類。 70 // 若是tree[x].relation和tree[temp].relation同爲0,意味着根節點與temp同類,temp與x同類,x與根節點也一定同類。 71 if(tree[x].relation == tree[temp].relation) 72 { 73 tree[x].relation = 0; 74 } 75 // tree[x].relation != tree[temp].relation意味着tree[x].relation和tree[temp].relation一個爲1,一個爲0, 76 // 若是tree[temp].relation爲false,tree[temp].relation爲1,意味着根節點和temp同類,temp與x不一樣類,那麼x與根節點必然不一樣類 77 // 若是tree[temp].relation爲true,tree[x].relation爲0,意味着根節點和temp不一樣類,temp與x同類,那麼x與根節點必然不一樣類 78 else 79 { 80 tree[x].relation = 1; 81 } 82 return tree[x].parent;// 返回根節點下標 83 } 84 else 85 { 86 return x; 87 } 88 } 89 90 void DisJoinSet ::Union(int x,int y) 91 { 92 int rootx = Find(x); 93 int rooty = Find(y); 94 if(rootx == rooty) 95 { 96 return ; 97 } 98 if(tree[rootx].rank > tree[rooty].rank) 99 { 100 tree[rooty].parent = rootx; 101 // 此時rooty與其根結點rootx的關係如何肯定?由於Find方法也在進行路徑壓縮,x的父節點是rootx,y的父節點的rooty 102 // 若是tree[x].relation和tree[y].relation均爲1,說明x和rootx不一樣類,y和rooty不一樣類,而已知x和y不一樣類,所以rooty和rootx不一樣類; 103 // 若是tree[x].relation和tree[y].relation均爲0,說明x和rootx同類,y和rooty同類,而已知x和y不一樣類,所以rooty和rootx不一樣類 104 if(tree[x].relation == tree[y].relation) 105 { 106 tree[rooty].relation = 1; 107 } 108 // 若是tree[x].relation爲1,tree[y].relation爲0,說明x和rootx不一樣類,y和rooty同類,而已知x和y不一樣類,所以rooty和rootx必同類; 109 // 若是tree[x].relation爲0,tree[y].relation爲1,說明x和rootx同類,y和rooty不一樣類,而已知x和y不一樣類,所以rooty和rootx必同類; 110 else 111 { 112 tree[rooty].relation = 0; 113 } 114 } 115 else 116 { 117 tree[rootx].parent = rooty; 118 if(tree[rootx].rank == tree[rooty].rank) 119 { 120 tree[rooty].rank ++; 121 } 122 // 此時rooty與其根結點rootx的關係如何肯定?由於Find方法也在進行路徑壓縮,x的父節點是rootx,y的父節點的rooty 123 // 若是relation[x]和relation[y]均爲true,說明x和rootx不一樣類,y和rooty不一樣類,而已知x和y不一樣類,所以rooty和rootx不一樣類; 124 // 若是relation[x]和relation[y]均爲false,說明x和rootx同類,y和rooty同類,而已知x和y不一樣類,所以rooty和rootx不一樣類 125 if(tree[x].relation == tree[y].relation) 126 { 127 tree[rootx].relation = 1; 128 } 129 // 若是tree[x].relation爲1,tree[y].relation爲0,說明x和rootx不一樣類,y和rooty同類,而已知x和y不一樣類,所以rooty和rootx必同類; 130 // 若是tree[x].relation爲0,tree[y].relation爲1,說明x和rootx同類,y和rooty不一樣類,而已知x和y不一樣類,所以rooty和rootx必同類; 131 else 132 { 133 tree[rootx].relation = 0; 134 } 135 } 136 } 137 138 139 bool DisJoinSet::itsSame(int x,int y) 140 { 141 return (tree[x].relation == tree[y].relation); 142 } 143 144 145 int main() 146 { 147 int T; 148 while(scanf("%d",&T) !=EOF )// 沒有EOF 會 OLE 149 { 150 if(T == 0)break; 151 for(int i = 0; i < T; i++) 152 { 153 int N; 154 int M; 155 scanf("%d%d",&N,&M); 156 DisJoinSet dis(N); 157 char s1[2]; 158 int s2,s3; 159 for(int i= 0; i < M ;i ++) 160 { 161 scanf("%s%d%d",s1,&s2,&s3); 162 int pa = dis.Find(s2); 163 int pb = dis.Find(s3); 164 if(s1[0] == 'A') 165 { 166 if(pa != pb) 167 { 168 cout<<"Not sure yet."<<endl; 169 } 170 else if(dis.itsSame(s2,s3) ) 171 { 172 cout<<"In the same gang."<<endl; 173 } 174 else//根相同 可是rela不一樣,說明再也不統一gangs 175 { 176 cout<<"In different gangs."<<endl; 177 } 178 } 179 if(s1[0]=='D') 180 { 181 if(pa != pb) 182 { 183 dis.Union(s2,s3); 184 } 185 186 } 187 } 188 } 189 } 190 return 0; 191 }