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.

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.

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;
        }
    }   
}

猜你喜欢

转载自www.cnblogs.com/dyhaohaoxuexi/p/12551610.html