【35.12%】【POJ 1988】Cube Stacking

来源:互联网 发布:美女图片采集源码 编辑:程序博客网 时间:2024/05/18 08:13

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

USACO 2004 U S Open

【题解】

题目的意思:
给你n个有标号的木块。
一开始全部摆放在地面上。
然后M 1 6的话,就是把地面上的标号1木块叠在6木块上面.
1
6 2 3 4 5
这时1下面有一个木块6所以C1==1;
再M 2 4,即把2号木块叠在4号木块上面
1 2
6 3 4 5
然后M 2 6即把2号木块所在的堆整个放在1号木块所在的堆
2
4
1
6 3 5
这样4号下面就只有两个木块;
做法:
带权并查集。
父亲指向底端的木块。
re[x]表示当前这个木块下面有多少个木块;
cnt[x]表示x个节点下面包括自己有多少个木块;
用带权向量(我也不知道有没有这个名词,但是听起来挺厉害的。)转移的时候。就不用那么麻烦了;
假设x和y的根节点分别为a,b;
则f[a]=b;
表示把a放在b所在堆的上面;
则a下面需要增加的代价就是cnt[b];
加上去就好了
至于a的上面的元素。会在ff函数里面进行路径压缩的时候累加上去;
所以不用担心。
和银河英雄传说那题很像。
还是安利下带权并查集的通解
http://blog.csdn.net/harlow_cheng/article/details/52737486

#include <cstdio>#include <iostream>using namespace std;const int MAXN = 30000;int f[MAXN+100], re[MAXN+100],cnt[MAXN+100];void input(int &r){    r = 0;    char t = getchar();    while (!isdigit(t)) t = getchar();    while (isdigit(t)) r = r * 10 + t - '0', t = getchar();}int ff(int x){    if (f[x] == x)        return x;    int olfa = f[x];    f[x] = ff(f[x]);    re[x] = re[x] + re[olfa];    return f[x];}int main(){    //freopen("F:\\rush.txt", "r", stdin);    for (int i = 1; i <= MAXN; i++)        f[i] = i, re[i] = 0,cnt[i] =1;    int p;    input(p);    for (int i = 1; i <= p; i++)    {        char key[5];        scanf("%s", key);        if (key[0] == 'M')        {            int x, y;            input(x); input(y);            int a = ff(x), b = ff(y);            if (a != b)            {                f[a] = b;                re[a] = re[a]+cnt[b];                cnt[b] += cnt[a];            }        }        else        {            int x;            input(x);            ff(x);            printf("%d\n", re[x]);        }    }    return 0;}
0 0
原创粉丝点击