POJ 1988(带权并查集)
            
            
              
POJ 1988
- 题目问的是包括x方块的堆 下面的 所有方块的个数,而不是方块x下面所有方块的个数,
 
- 将最下面的方块作为根节点(父亲节点设置时带方向)
 
- 一个数组记录此堆的数量,另一个数组记该点下面方块的个数
 
- find(x)时,更新所有点的下面方块个数,
 
- 询问点x的结果时,首先要find(x),使的结果为该堆的根节点下面的方块数量
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
   | #include <iostream> using namespace std; const int maxn = 3e4+5; int tot[maxn],pre[maxn],down[maxn]; void init() { 	for (int i=1; i<maxn; i++) { 		tot[i] = 1;  		pre[i] = i;  		down[i] = 0;  	} } int find(int x) { 	if (x != pre[x]) { 		int lastx = pre[x]; 		pre[x] = find(pre[x]); 		down[x] += down[lastx];  	}  	return pre[x]; } void merge(int a,int b) { 	int root_a = find(a); 	int root_b = find(b); 	if (root_a != root_b) { 		pre[root_a] = root_b; 		 		down[root_a] = tot[root_b];  		tot[root_b] += tot[root_a]; 	} } int main() { 	freopen("a.txt","r",stdin); 	int p; 	cin >> p;
  	init();
  	char ch; 	int u,v; 	for (int k=0; k<p; k++) { 		cin >> ch; 		if (ch == 'M') { 			cin >> u >> v; 			merge(u,v);		 		} 		else { 			cin >> u;
  			find(u);  			printf("%d\n",down[u]); 		} 	} 	return 0; }
 
  |