TOJ 3294. Building Block 并查集

3294.   Building Block Time Limit: 1.0 Seconds Memory Limit: 65536K
Total Runs: 840   Accepted Runs:235

John are playing with blocks. There are N blocks (1 ≤ N ≤ 30000) numbered 0.. N-1. Initially, there are N piles, and each pile contains one block. Then John do some operations P times (1 ≤ P ≤ 1000000). There are two kinds of operation:

M X Y : Put the whole pile containing block X up to the pile containingY. IfX and Y are in the same pile, just ignore this command.
C X : Count the number of blocks under block X

You are request to find out the output for each C operation.

Input

The first line contains integer P. Then P lines follow, each of which contain an operation describe above.

Output

Output the count for each C operations in one line.

Sample Input

6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4

Sample Output

1
0
2

Author:SUN, Chao



Source:Multi-School Training Contest - TOJ Site #1

题意: 有N个木块,放在N个平台上,M x,y移动有x的平台,全部放到y的平台上

c x 输出x木块下有几个木块

 

一道并查集的题;

但是由于思考的不够细,一直wa,,再加上不懂c读取字符,导致了几次re。 一次ce

连水题都被难倒了,,贴一下。。。纪念又一个悲剧

 

设置三个数字: up [x]  x上有几个木块

down[x]  下有几个木块

pre[x]是下面的一个木块是几号

//一堆木块,除了最底下的父亲是自己外,其他的木块父亲最终指向最底下

#include<cstdio>
using namespace std;
const int maxn = 30005;
int up[maxn];//记录木块上面的木块个数
int down[maxn];//记录木块下面的木块个数
int pre[maxn];//记录父亲结点
int stack[maxn];//堆栈
int sp = 0;
int find_pre(int root){//查找根
    int u = root;
    sp = 0;
    while(pre[root] != root)//找根,且把链上的结点都加入栈
    {
        stack[sp++] = root;
        root = pre[root];
    }
    for(int i = sp - 2 ;i > -1; i--)//更新链上的每个结点
    {// -2 的原因是如果他的父亲是最底下的木块,就不用更新了。因为在  合并的时候更新过 1.0处
        down[stack[i]] += down[stack[i+1]];
        pre[stack[i]] = root;
    }
    return root;
}

int main()
{
    int N,x,y;
    char a;
    while(scanf("%d",&N) != EOF)
    {
        for(int i = 0; i <= maxn; i++)
        {
            pre[i] = i;
            up[i] = 0;
            down[i] = 0;
        }
        for(int i = 0;i < N; i++)
        {
            getchar();
            a = getchar();//读取字符
            if(a == 'M')
            {
                scanf("%d%d",&x,&y);  //1.0,更新点
                int fx = find_pre(x);//找x的根
                int fy = find_pre(y);//找y的根
                if(fx == fy) continue;
                down[fx] += up[fy] + 1;//更新结点信息
                up[fy] += up[fx] + 1;
                pre[fx] = fy;
            }
            else
            {
                scanf("%d",&x);
                find_pre(x);
                printf("%d\n",down[x]);
            }
        }
    }
    return 0;
}

 

你可能感兴趣的:(ACM)