并查集 POJ 1988 Cube Stacking

题目传送门:    -------->这里<----------

题目大意:

  有标记1-N的方块,初始时一个砖块是一堆。然后进行以下操作

  M X Y : 将 X 砖块所在堆 叠到 Y 砖块所在堆上面;

  C X :数在 X 砖块所在堆中 叠在X砖块下的砖块个数;

  1<=N<=30000;

思路:

  并查集,每一个砖块堆是一个集合。将每一堆的最上面一块砖设为根,合并时更新 Y 堆的根的 father 和 val (在Y上面的方块数) 。 要达到这些目的,需要一个all数组,来记录每一堆里的砖块总数,和一个val数组,来记录具体某一块砖上面的砖块个数。输出时,输出all - val - 1;在find函数中进行路径压缩的,记住回溯时将val值相加。

初始时   all 数组 全为 1 ,不能用memset初始化int 数组全为1,因为memset是按字节填充,会使值错误。

    val 数组 全为 0。

    father[x] = [x];

代码:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #define MAX 30010
 5
 6 using namespace std;
 7 int val[MAX];
 8 int all[MAX];
 9 int father[MAX];
10 void init()
11 {
12     memset(val,0,MAX * sizeof(int));
13     for(int i = 0 ; i < MAX ; i++)
14     {
15         father[i] = i;
16         all[i] = 1;
17     }
18     return ;
19 }
20 int Find_Root(int x)
21 {
22     if(father[x] == x)
23     {
24         return x;
25     }
26     int temp = father[x];
27     father[x] = Find_Root(father[x]);
28     val[x] += val[temp];
29     return father[x];
30 }
31
32
33 void M (int a ,int b)
34 {
35     if(a == b) return ;
36     father[a] = b;
37     val[a] += all[b];
38     all[b] += all[a];
39     return ;
40 }
41
42 void C(int a)
43 {
44     cout << all[Find_Root(a)] - val[a] - 1 << endl;
45     return ;
46 }
47
48
49 int main()
50 {
51     int T;
52     while(~scanf("%d",&T))
53     {
54         init();
55         for (int i = 0; i < T; ++i)
56         {
57             char op;
58             int n,m;
59             cin >> op ;
60             if(op == ‘M‘)
61             {
62                 cin >> n >> m;
63                 M(Find_Root(m),Find_Root(n));
64             }
65             else if(op == ‘C‘)
66             {
67                 cin >> n;
68                 C(n);
69             }
70             //////////////////////////////
71         }
72     }
73     return 0;
74
75 }
时间: 2024-12-14 06:35:38

并查集 POJ 1988 Cube Stacking的相关文章

POJ 1988 Cube Stacking(并查集+路径压缩)

题目链接:id=1988">POJ 1988 Cube Stacking 并查集的题目 [题目大意] 有n个元素,開始每一个元素自己 一栈.有两种操作,将含有元素x的栈放在含有y的栈的顶端,合并为一个栈. 另外一种操作是询问含有x元素以下有多少个元素. 用sum数组储存每一个栈中的元素个数.每次合并的时候将sum加到 父亲节点.也就是每一个栈的最底部. 用under数组储存当前节点以下有多少元素.每次合并的时候,就能够将顶端元素的under赋值为父节点也就是栈最底部的sum. void U

POJ 1988 Cube Stacking

Cube Stacking Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 18820   Accepted: 6530 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 w

POJ 1988 Cube Stacking(转)

这道题的思路,就是每次记下该点到父结点的个数,并记录下其下的结点个数.之后,每次"C"时,将总的减去它所压的方块,即答案!!!(也是参考别人的~-?) <pre name="code" class="cpp">#include<stdio.h> #include<iostream> using namespace std; #define max 30010 struct node { int parent;/

[POJ 1988] Cube Stacking (带值的并查集)

题目链接:http://poj.org/problem?id=1988 题目大意:给你N个方块,编号从1到N,有两种操作,第一种是M(x,y),意思是将x所在的堆放到y所在的堆上面. 第二种是C(x),意思是数x方块下面有多少个方块. 把两堆合成一堆,这个可以用并查集来实现,问题是,怎么样维护x方块下面有多少个方块呢? 先来分析一下题目,按照样例,我们有6个方块,1,2,3,4,5,6. 令Cnt(x) = C(x)+1. 先执行M(1,6),此时Cnt(1) = 2, Cnt(6) = 1 再

POJ 1988 Cube Stacking (带权并查集)

题目链接:http://poj.org/problem?id=1988 有n个元素,开始每个元素自己 一栈,有两种操作,将含有元素x的栈放在含有y的栈的顶端,合并为一个栈.第二种操作是询问含有x元素下面有多少个元素. 经典的带权并查集,cnt表示包含这个元素的集合中所有元素个数,dis表示这个元素离最上面元素的个数(距离). 看代码领会一下吧. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio>

poj.1988.Cube Stacking(并查集)

Cube Stacking Time Limit:2000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 1988 Description Farmer John and Betsy are playing a game with N (1 <= N <= 30,000)identical cubes labeled 1 through N. They st

POJ 1988 Cube Stacking (带权并查集)

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 typ

POJ 1988 Cube Stacking 【带权并查集】

<题目链接> 题目大意: 有几个stack,初始里面有一个cube.支持两种操作: 1.move x y: 将x所在的stack移动到y所在stack的顶部. 2.count x:数在x所在stack中,在x之下的cube的个数. 解题分析:由于要实现大量数的移动和归属关系,所以想到可能要用并查集,但是毫无疑问,普通的并查集不能够实现统计在x下的cube个数这一功能,所以我们通过带权并查集来实现,每一个stack,以最高的点为根,然后每一个点维护两个权值,它的子树节点个数(包括它自身),和它到

POJ 1988 Cube Stacking (种类并查集)

题目地址:POJ 1988 这道题的查找合并的方法都能想的到,就是一点没想到,我一直天真的以为查询的时候,输入后能马上输出,这样的话在合并的时候就要所有的结点值都要算出来,但是经过路径压缩之后,没办法全部都处理到,如果不压缩妥妥的TLE..于是看了看网上的题解.才发现自己是多么的天真(ben,四声)..在查询的时候只要找一次跟就可以了..这样不需查询的也就没必要处理出来.反而更省时. 这题的基本思路是很好想的.另开两个数组,一个记录以此节点为根的子节点的数目(这样合并的时候只需要加另一个根的数目