POJ 1988 Cube Stacking(带权并查集)

题意:

给定 n 个 方块, 然后有 p 个操作

操作M (a , b) , 就是将a方块所在的那一堆方块放到 b 上面。

操作C (x) , 就是询问x方块下面有多少方块

分析:

记录方块到父亲的距离dis, 还有最底的方块的cnt。

两个方块合并时,合并方块堆的父亲dis += 最底方块堆的cnt ,最底的方块堆的cnt 加上合并方块堆的 cnt

那么对于每个询问, 只要做一次路径压缩, 从根节点一直更新到询问点, 那么就能更新出询问点的长度

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int Maxn =  10 ;
 4 int P;
 5 int F[Maxn], cnt[Maxn], dis[Maxn];
 6 void init(){
 7     for(int i = 0; i < Maxn; i++)
 8         F[i] = i, cnt[i] = 1, dis[i] = 0;
 9 }
10 
11 
12 int Find (int x){
13     if (F[x] != x){
14         int temp  = F[x]; //设置延时,最后从父节点回溯的时候再更新,注意与下面的对比
15         F[x] = Find(F[x]);
16         dis[x] += dis[temp];
17         return F[x];
18     }
19     return x;
20 }
21 
22 /* 不能写成以下的形式, 因为这样会先更新了自己, 然后再更新父节点
23 int Find (int x){
24     if (F[x] != x){
25         dis[x] += dis[F[x]];
26         F[x] = Find(F[x]);
27         return F[x];
28     }
29     return x;
30 }
31 */
32 
33 
34 int Merge(int a, int b){
35     int t1 = Find(a), t2 = Find(b);
36     if(t1 != t2){
37         F[t1] = t2; //将t1的根改为t2
38         dis[t1] = cnt[t2]; //那么t1到根的距离就是cnt[t2]
39         cnt[t2] += cnt[t1]; //然后cnt[t2]这一堆就要加上cnt[t1]
40     }
41 }
42 int main(){
43     freopen("debug.txt","r", stdin);
44     init();
45     scanf("%d", &P);
46     while(P--)
47     {
48 
49         char ch[9];
50         scanf("%s", ch);
51         if(ch[0] == 'M'){
52             int a, b;
53             scanf("%d %d", &a, &b);
54             Merge(a,b);
55         }
56         else{
57             int x;
58             scanf("%d", &x);
59             Find(x);
60             printf("%d
", dis[x]);
61         }
62     }
63     return 0;
64 }
原文地址:https://www.cnblogs.com/Jadon97/p/7814126.html