POJ1988 Cube Stacking (带权并查集)
Cube Stacking
Time Limit: 2000MS | Memory Limit: 30000K | |
Total Submissions: 31012 | Accepted: 10904 | |
Case Time Limit: 1000MS |
Description
Farmer John and Betsy are playing a game with N (1 <= N <= 30,000)identical cubes labeled 1 through N. They start with N stacks, each containing a single cube. Farmer John asks Betsy to perform P (1<= P <= 100,000) operation. There are two types of operations:
moves and counts.
* In a move operation, Farmer John asks Bessie to move the stack containing cube X on top of the stack containing cube Y.
* In a count operation, Farmer John asks Bessie to count the number of cubes on the stack with cube X that are under the cube X and report that value.
Write a program that can verify the results of the game.
moves and counts.
* In a move operation, Farmer John asks Bessie to move the stack containing cube X on top of the stack containing cube Y.
* In a count operation, Farmer John asks Bessie to count the number of cubes on the stack with cube X that are under the cube X and report that value.
Write a program that can verify the results of the game.
Input
* Line 1: A single integer, P
* Lines 2..P+1: Each of these lines describes a legal operation. Line 2 describes the first operation, etc. Each line begins with a 'M' for a move operation or a 'C' for a count operation. For move operations, the line also contains two integers: X and Y.For count operations, the line also contains a single integer: X.
Note that the value for N does not appear in the input file. No move operation will request a move a stack onto itself.
* Lines 2..P+1: Each of these lines describes a legal operation. Line 2 describes the first operation, etc. Each line begins with a 'M' for a move operation or a 'C' for a count operation. For move operations, the line also contains two integers: X and Y.For count operations, the line also contains a single integer: X.
Note that the value for N does not appear in the input file. No move operation will request a move a stack onto itself.
Output
Print the output from each of the count operations in the same order as the input file.
Sample Input
6 M 1 6 C 1 M 2 4 M 2 6 C 3 C 4
Sample Output
1 0 2
题目大意与分析
本题在并查集的基础上,要求输出当前节点的子节点数量,其实可以转化为带权并查集的问题,求出当前节点的祖先的总子孙数量,减去当前节点到祖先的距离再减一即可
带权并查集的介绍:https://blog.csdn.net/yjr3426619/article/details/82315133
Up[x]代表x到自己的祖先的距离(也就是上面有多少节点)
sums[x]代表以x为根节点的子孙数量(只对根节点有效,因为在合并时,非根节点的sums值将不再被更新)
s[x]代表x的祖先
#include <iostream> #include <string.h> #include <stdio.h> #include <vector> #include <stack> #include <queue> #include <algorithm> #include <math.h> #include <cstdio> using namespace std; int s[30005],sums[30005],Up[30005],p; char C; int findf(int x){ if(s[x]==x) { return x; } else { int fx=s[x]; s[x]=findf(s[x]); Up[x]+=Up[fx]; //修改x的Up值,因为x的父节点变化了,此时不需要修改sum值 return s[x]; } } void hebing (int x, int y){ int fx=findf(x); int fy=findf(y); if(fx!=fy){ s[fy]=fx; Up[fy]+=sums[fx]; //被合并时加上移过来的数量 sums[fx]+=sums[fy]; //只有在合并的时候才需要修改根节点的sum值 此时fy被合并 不作为根节点存在 } } int main(void) { cin>>p; for(int i=1;i<30005;i++) { sums[i]=1; Up[i]=0; s[i]=i; } while(p--) { cin>>C; if(C=='M') { int a,b; cin>>a>>b; hebing(a,b); } else { int a; cin>>a; int fa=findf(a); cout<<sums[fa]-Up[a]-1<<endl; } } }