并查集/poj 1988 Cube Stacking
题意
一开始若干个元素自己为一个栈,给出n个操作,有如下两种:
1.M a b :表示把元素a所在的栈整个压在含有元素b的栈的顶端
2.C x :查询元素x所在的栈,x下方有几个元素,输出
分析
题意简单明了:并查集
除了数组f[i]用来记录i的祖先,也就是顶端元素
另需要数组rank[i],记录i所在的栈一共有多少个元素(i为栈顶)
数组up[i],记录i上面有多少个元素
则答案为rank[find(x)]-up[x]-1
至于在find和union中如何维护rank和up:
在find中只需维护up,即up[x]+=up[father[x]];
在union中需要维护up和rank,这时候rank起作用了。
例如将x所在的栈压在y所在栈顶端,则y所在栈的顶端father[y]上元素的个数即为x所在栈所有元素个数,即up[father[y]]=rank[father[x]]
(看了好多题解 表示不明白他们为什么要写up[father[y]]+=rank[father[x]],个人觉得用不着+啊,而且+不+都能AC...躺倒)
而将x所在的栈压在y所在栈顶端后,x所在栈的总元素个数将会加上y所在栈元素个数,即rank[father[x]]+=rank[father[y]]
Accepted Code
1 { 2 PROBLEM:poj 1988 3 AUTHER:Rinyo 4 MEMO:并查集 5 } 6 7 Program poj1988; 8 Const 9 Infile = 'poj1988.in'; 10 Outfile = 'poj1988.out'; 11 Var 12 f,rank,up:Array[0..30030]Of Longint; 13 n,i,a,b:Longint; 14 ch:Char; 15 Function find(x:Longint):Longint; 16 Var 17 fx:Longint; 18 Begin 19 If f[x]=x Then Exit(x); 20 fx:=f[x]; 21 f[x]:=find(fx); 22 up[x]:=up[x]+up[fx]; 23 Exit(f[x]); 24 End; 25 Procedure union(x,y:Longint); 26 Var 27 fx,fy:Longint; 28 Begin 29 fx:=find(f[x]);fy:=find(f[y]); 30 If fx<>fy Then Begin 31 f[fy]:=fx; 32 up[fy]:=rank[fx]; 33 rank[fx]:=rank[fx]+rank[fy]; 34 End; 35 End; 36 37 Begin 38 Assign(input,infile);Reset(input); 39 Assign(output,outfile);Rewrite(output); 40 ReadLn(n); 41 For i:=0 To 30030 Do rank[i]:=1; 42 Fillchar(up,sizeof(up),0); 43 For i:=0 To 30030 Do f[i]:=i; 44 For i:=1 To n Do Begin 45 Read(ch); 46 If ch='M' Then Begin 47 ReadLn(a,b); 48 union(a,b); 49 End Else Begin 50 ReadLn(a); 51 WriteLn(rank[find(a)]-up[a]-1); 52 End; 53 End; 54 Close(input);Close(output); 55 End.