poj 1988 Cube Stacking

poj 1988 Cube Stacking

http://poj.org/problem?id=1988

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
题目大意:
有块积木,开始时它们都属于不同的集合。
然后输入p,表示有p个操作。每个操作都有一个t,如果t==M,那么输入x,y,把x所在集合的所有积木,都堆到y所在集合的上面;如果t==C,那么输入x,查询并输出x下面有多少个积木(不包括x本身)。
解题思路:加权并查集
先设2个数组,under[i]=j表示在积木i下面有j个积木;tot[i]=j表示i所在集合一共有j个积木。

由此可以看出,如果我们要把x摞到y的上面,

在合并操作时,x的下面多了y所在集合的全体,所以under[x]=under[x]+tot[y];x的father指向y,y所代表的集合总数多了x所在集合的全体,所以tot[y]=tot[x]+tot[y]

上面还更新了tot[x]=0,这个在代码中更不更新无所谓,并查集合并操作合并祖先节点,x的father指向了y,x不会再作为祖先节点出现

在查询祖先节点时,我们需要维护under[]

在路径压缩中更新under时,要先记录下i的祖先节点,在递归回溯时先加上i原父节点的under,再把i的父节点更新为祖先节点。
#include<cstdio>
#include<iostream>
using namespace std;
int p,father_x,father_y;
char c;
int x,y,un;
int under[30001],tot[30001],fa[30001];//under:下面有几个积木  tot:集合一共有几个积木
int find(int i)
{
    //先更新under再路径压缩 
    if(fa[i]!=i) 
    {
        int tmp=find(fa[i]);
        under[i]+=under[fa[i]];
        fa[i]=tmp;
    }
    return fa[i];
}
void unionn()//x摞到y的上面 
{
    under[father_x]+=tot[father_y];
    tot[father_y]+=tot[father_x];
    fa[father_x]=father_y;
}
int main()
{
    scanf("%d",&p);
    for(int i=0;i<=30000;i++) tot[i]=1,fa[i]=i;
    while(p--)
    {
        cin>>c;
        if(c=='M')
        {
            scanf("%d%d",&x,&y);
            father_y=find(y);
            father_x=find(x);
            if(father_x!=father_y)
            unionn();
        }
        else 
        {
            scanf("%d",&x);
            find(x);
            printf("%d
",under[x]);
        }
    }
}
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6293889.html