poj 1988 Cube Stacking(并查集)

简介:
Cube Stacking
Time Limit: 2000MS   Memory Limit: 30000K
Total Submissions: 14901   Accepted: 5037
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

 

超时代吗,虽然功能是实现了但却是一直到超时,因为没有真正的掌握并查集使用方法:

复制代码
/*
* 方法一,超时,这里用了一个lower 来表示找下一个立方块,
* 这里使用的是循环,所以么每次都会把下方的cube遍历一遍,造成超时
*/

#include <iostream>
#include <stdio.h>
#define MAXNUM 30001
using namespace std;

typedef struct
{
    int count;//记录改立方体下方所有的立方体个数
    int parent;//指向立方体所在堆最上边的那个立方体
    int lower;//指向当前立方体的下方那个块
}Cube;
Cube cube[MAXNUM];

void init()
{
    for(int i = 1;i < MAXNUM; i++)
    {
        cube[i].count = 0;//初始化每个立方体下方均为0
        cube[i].parent = i;//初始化每个立方体为单个堆,并且为当前堆最上边
        cube[i].lower = 0;
    }
}

//合并x,y所在的堆
void union_set(int x,int y)
{
    int lower_parent;//下方堆中格子的最父节点
    int lower_cube;//下方格子下标
    int parent;//上方堆的最父节点下标

    parent = cube[x].parent;
    lower_parent = cube[y].parent;
    lower_cube = x;
    //更新上方的stack,在当前的cube下所有的count都要变化
    while(cube[lower_cube].lower!=0)
    {
        cube[lower_cube].count = cube[lower_parent].count+1;
        lower_cube = cube[lower_cube].lower;
    }
    cube[lower_cube].count = cube[lower_parent].count+1;
    //同时更新最下方那个块的下边,就是下边stack的最上边的块
    cube[lower_cube].lower = lower_parent;

    //更新下方所有块的父节点,此时成为一个大的堆
    while(cube[lower_parent].lower!=0)
    {
        cube[lower_parent].parent = parent;
        lower_parent = cube[lower_parent].lower;
    }
    cube[lower_parent].parent = parent;
}

int main()
{
    //有P个操作
    int P;
    //命令的种类,
    //M X Y ,将X立方体所在的堆移到Y立方体所在的堆的上面
    //C X 输出在X所在的堆上,在X立方体下面的立方体个数。
    char ch;
    int x,y;
    init();
    scanf("%d",&P);
    while(P--)
    {
        scanf("\n%c",&ch);
        //getchar();
        //cin>>ch;
        if(ch=='M')
        {
            scanf("%d%d",&x,&y);
            union_set(x,y);//合并集合
        }
        else if(ch=='C')
        {
            scanf("%d",&x);
            printf("%d\n",cube[x].count);
        }
    }
    return 0;
}
复制代码

并查集AC代码

复制代码
#include <iostream>
#include <stdio.h>
#define MAXNUM 30010
using namespace std;

typedef struct
{
    int count;//记录改立方体下方所有的立方体个数
    int parent;//指向立方体所在堆最上边的那个立方体
    int num;
}Cube;
Cube cube[MAXNUM];

void init()
{
    for(int i = 1;i < MAXNUM; i++)
    {
        cube[i].count = 0;//初始化每个立方体下方均为0
        cube[i].num = 1;
        cube[i].parent = -1;//初始化每个立方体为单个堆,并且为当前堆最下边位置
    }
}
int find(int a)
{
    //自己指向自己,说明自己是根
    if(cube[a].parent == -1)
    return a;
    int tem = cube[a].parent;
    cube[a].parent = find(cube[a].parent);//压缩路径,使得所有的根是同一个
    cube[a].count += cube[tem].count;//更新当前的块下方的数目,是
    return cube[a].parent;//返回终极根
}

void union_set(int x,int y)
{
    cube[x].parent = y;
    cube[x].count += cube[y].num;
    cube[y].num += cube[x].num;
}

int main()
{
    //有P个操作
    int P;
    //命令的种类,
    //M X Y ,将X立方体所在的堆移到Y立方体所在的堆的上面
    //C X 输出在X所在的堆上,在X立方体下面的立方体个数。
    char ch;
    int x,y,rx,ry;
    init();
    scanf("%d",&P);
    while(P--)
    {
       // scanf("%s",ch);
       cin>>ch;
        if(ch=='M')
        {
            scanf("%d%d",&x,&y);
            rx = find(x);
            ry = find(y);
            if(rx!=ry)
            union_set(rx,ry);//合并集合
        }
        else if(ch=='C')
        {
            scanf("%d",&x);
            find(x);
            printf("%d\n",cube[x].count);
        }
    }
    return 0;
}
复制代码











本文转自NewPanderKing51CTO博客,原文链接:http://www.cnblogs.com/newpanderking/archive/2012/09/06/2673678.html  ,如需转载请自行联系原作者
相关文章
|
10月前
POJ 1988 Cube Stacking
POJ 1988 Cube Stacking
|
11月前
|
人工智能
POJ 2299 Ultra-QuickSort(树状数组+离散化+求逆序数)
POJ 2299 Ultra-QuickSort(树状数组+离散化+求逆序数)
codeforces1253——D. Harmonious Graph(并查集)
codeforces1253——D. Harmonious Graph(并查集)
74 0
UPC Graph (最小生成树 || 并查集+二分)
UPC Graph (最小生成树 || 并查集+二分)
77 0
Harry Potter and The Vector Spell-gym101669D(矩阵的秩-并查集)
题意: 给出一个0 1矩阵,这个矩阵中每一列有且只有两个1,求这个矩阵的秩 输入一行中1的数量x,然后后面x个数代表1出现的列位置 求出这个矩阵的秩 方法: 思维并查集 将每一列的两个1所在的行编号连一条边,然后求一下最小生成树就好 其实就是我们维护一个并查集,在这个并查集里面的所有点都可以两两组合形成一列,如果不在同一个集合里面,就会对答案+1
91 0
Harry Potter and The Vector Spell-gym101669D(矩阵的秩-并查集)
|
C语言
HDOJ/HDU Tempter of the Bone(深搜+奇偶性剪枝)
HDOJ/HDU Tempter of the Bone(深搜+奇偶性剪枝)
85 0