zoukankan      html  css  js  c++  java
  • POJ 1988 Cube Stacking【并查集的简单应用 堆木块】

    Time Limit: 2000MS   Memory Limit: 30000K
    Total Submissions: 15951   Accepted: 5448
    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
    

    Source


    题意:给你一定数目的堆(PS:堆的数目不确定,但是不超过最大值 30,000)

                初始时每个堆都有且仅有一个方块 ,其编号安装所在堆的编号编为 1 ... 30,000 。

                输入一个数 P,表示有 P 个操作:

                C     x              计算编号为 x 的方块下面有多少个方块,输出结果。

                M     x         y   将编号为 x 的方块所在的堆放到编号为 y 所在的堆的上面。


    算法并查集


    思路【盗版的,惭愧】:

              以堆底为根【重要】(PS:因为方便用堆底的下标记录当前堆的总方块数)

              p[] 记录父节点

              r[] 记录当前方块下面的方块个数

              sum[] 记录当前堆的方块总个数,记录堆底【根】的即可。

             并查集模板

             1.找根节点:注意向下更新时 r[] 要加上父亲的 r[]

             2.合并:因为是前者放在后者上面,又是应该以堆底为根,所以 p[fx] = fy;

                           相应要更新 r[fx] = num[fy]; // x 的根【堆底】压 y 所在堆的所有方块块

                                               num[fy] += num[fx]; // 被压的堆的方块总数更新


      

    G Accepted 484 KB 250 ms C++ 1173 B 2013-04-10 16:48:07
    #include<cstdio>
    
    const int maxn = 30000+10;
    
    int p[maxn];
    int r[maxn]; //下面的个数
    int sum[maxn]; //总个数
    
    int find(int x)
    {
        if(x == p[x]) return x;
    
        int t = p[x];
        p[x] = find(p[x]);
        r[x] = r[x]+r[t]; //自己下面的+父亲下面的
    
        return p[x];
    }
    
    void Union(int x, int y)
    {
        int fx = find(x);
        int fy = find(y);
    
        if(fx == fy) return;
    
        p[fx] = fy; //以堆底为根
        r[fx] = sum[fy]; //上面的堆底压了 y所在堆的所有木块
        sum[fy] = sum[fy]+sum[fx]; //更新当前堆的木块个数 保存在根中
    }
    
    void set()
    {
        for(int x = 1; x < maxn; x++)
        {
            p[x] = x;
            r[x] = 0;
            sum[x] = 1;
        }
    }
    int main()
    {
        int p;
        while(scanf("%d%*c", &p) != EOF)
        {
            set();
            char c;
            int x,y;
            while(p--)
            {
                scanf("%c", &c);
                if(c == 'M')
                {
                    scanf("%d%d%*c", &x, &y);
                    Union(x, y);
                }
                else if(c == 'C')
                {
                    scanf("%d%*c", &x);
                    find(x); //可能没有更新 r[] 输出前,更新根节点 
                    printf("%d\n", r[x]);
                }
            }
        }
        return 0;
    }
     


  • 相关阅读:
    Codeforces Gym
    洛谷试炼场一句话题解
    优先队列板子
    BZOJ 3524 [POI2014] Couriers/洛谷3567(可持久化线段树)
    hdu 4417 Super Mario(可持久化线段树)
    poj 2559 Largest Rectangle in a Histogram (单调栈)
    zoj 4019 Schrödinger's Knapsack
    hdu 1521 排列组合(指数型生成函数板子)
    hdu 2072 单词数(普通型生成函数板子)
    RabbitMQ广播:direct模式
  • 原文地址:https://www.cnblogs.com/freezhan/p/3219078.html
Copyright © 2011-2022 走看看