poj1988 Cube Stacking(并查集
题目地址:http://poj.org/problem?id=1988
题意:共n个数,p个操作。输入p。有两个操作M和C。M x y表示把x所在的栈放到y所在的栈上(比如M 2 6:[2 4]放到[1 6]上为[2 4 1 6]),C x为输出x下面有几个数。
思路:并查集每个集合以栈最下面的数为根,维护两个数组num[x]表示x所在集合节点总数,count[x]表示x下方节点个数。每次查找压缩路径的时候更新count(换父节点的时候每轮都把父节点的count加给儿子,就可以一直更新到x所在栈的最底下),合并的时候更新px的count和py的num(把x的栈放到y的栈上,x下面多了num[y]个节点,新栈总根y总数增加num[x]个)。【不管是M还是C,先found一下x,把x的fa[x]更新到栈的最底下,count[x]才是真正的数!】
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 4 using namespace std; 5 6 const int maxn = 30000 + 5; 7 struct c 8 { 9 int fa, count, num; 10 }cube[maxn]; 11 12 void init(int n) 13 { 14 for(int i = 1; i <= n; i++) 15 { 16 cube[i].fa = i; 17 cube[i].num = 1; 18 cube[i].count = 0; 19 } 20 } 21 22 int found(int x) 23 { 24 if(cube[x].fa == x) 25 return x; 26 int px = cube[x].fa; 27 cube[x].fa = found(cube[x].fa); 28 cube[x].count += cube[px].count; 29 return cube[x].fa; 30 } 31 32 void unite(int x, int y) 33 { 34 int px = cube[x].fa; 35 int py = cube[y].fa; 36 if(px != py) 37 { 38 cube[px].fa = py; 39 cube[px].count += cube[py].num; 40 cube[py].num += cube[px].num; 41 } 42 } 43 44 int main() 45 { 46 int p, x, y; 47 char opr; 48 init(maxn); 49 scanf("%d", &p); 50 while(p--) 51 { 52 getchar(); 53 scanf("%c", &opr); 54 if(opr == 'M') 55 { 56 scanf("%d%d", &x, &y); 57 int px = found(x); 58 int py = found(y); 59 if(px != py) 60 unite(x, y); 61 } 62 else 63 { 64 scanf("%d", &x); 65 found(x); 66 printf("%d\n", cube[x].count); 67 } 68 } 69 return 0; 70 }