POJ 1988 Cube Stacking 并查集 + 权值(隐含)

Cube Stacking
 
 
Time Limit: 2000MS Memory Limit: 30000K
Total Submissions: 19072 Accepted: 6643
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
题意 :
此题 M 1 6 代表将含编号1的木块堆放到含编号6的木块堆上面,C 1 是问编号1的木块下面有多少木块。
难点在于如何维护每个非节点的木块的权值,由于一个个枚举会超时,效率低,所以用并查集,那该怎么办呢?
首先开一个数组cnt[x]记录父节点x下的木块块数(包括x自己),再开dis[y]记录y到x的距离(即y 与 x 之间的木块数),则y下面的木块块数为cnt[x] - dis[y] - 1。
 
 
#include
    
    
     
     
#include
     
     
      
      
int f[30005];
int val[30005];
int dis[30005];/*节点与父节点的距离*/
int find(int x)
{
    if(f[x] == x)
        return x;
    int t = f[x];
        f[x] = find(f[x]);
        dis[x] += dis[t];
    return f[x];
}
void merge(int x,int y)
{
    x = find(x);
    y = find(y);
    if(x == y)
    return;
    f[y] = x;
    dis[y] = val[x];/*父节点下的木块数即距离*/
    val[x] += val[y];/*父节点下的木块数增加了val[y](y下(包括y)的木块数)*/
}
int main()
{
    int n,x,y,k;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i = 1; i <= 30000; i++)
        {
            f[i] = i;
            val[i] = 1;
            dis[i] = 0;
        }
        while(n--)
        {
            char t[5];
            scanf("%s",t);
            if(t[0] == 'M')
            {
                scanf("%d%d",&x,&y);
                merge(x,y);
            }
            else if(t[0] == 'C')
            {
                scanf("%d",&k);
                int m = find(k);
                printf("%d\n",val[m] - dis[k] - 1);
            }
        }
    }
}

     
     
    
    
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值