题目链接:http://poj.org/problem?id=1988

题意:有n个元素,开始每个元素各自在一个栈中,有两种操作,将含有元素x的栈放在含有y的栈的顶端,合并为一个栈。
第二种操作是询问含有x元素下面有多少个元素。
思路:

并查集,把每一堆看作一个栈,堆的下方看作栈顶。因为当我们知道栈中元素的总数,和某元素到“栈顶”的距离,
我们就能知道这个元素下面有多少元素。合并操作的时候,始终使用在下面栈的根来做合并之后的根,这样也就达到了栈中的根是栈中的“栈顶”元素的效果,我们只需在每个“栈顶”中记录该栈中的元素总数即可。然而我们还需要得知某元素到“栈顶”的距离,这样我们就需要记录每个元素到其父亲的距离,把它到根上所经过的距离加起来,即为它到“栈顶”的距离。这样我们就得出了结果。
 
这个图是在合并的时候的关键部分 
另外,在进行Find()操作时,有一句 under[x] += under[t[x].parent];这句话就是在递归寻找根结点时,计算出每个元素距离栈底(根)的距离。
 #include<iostream>
#include<stdio.h>
#include<cstring>
#include<cmath>
#include<vector>
#include<stack>
#include<map>
#include<set>
#include<list>
#include<queue>
#include<string>
#include<algorithm>
#include<iomanip>
using namespace std; struct node
{
int parent;
int date;
}; int * total;
int * under; class DisJoinSet
{
protected:
int n; node * tree;
public:
DisJoinSet(int n);
~DisJoinSet();
void Init();
int Find(int x);
void Union(int x,int y);
}; DisJoinSet::DisJoinSet(int n)
{
this->n = n;
tree = new node[n+];
total = new int[n+];
under = new int[n+];
Init();
}
DisJoinSet::~DisJoinSet()
{
delete[] under;
delete[] total;
delete[] tree;
} void DisJoinSet::Init()
{
for(int i = ;i <= n ;i ++)
{
tree[i].date = i;
tree[i].parent = i;
total[i] = ;
under[i] = ;
}
}
int DisJoinSet::Find(int x)
{
//int temp = tree[x].parent;
if(x != tree[x].parent)
{
int par = Find(tree[x].parent);
under[x] += under[tree[x].parent];//把父亲结点下面的个数加到自己头上
tree[x].parent = par;
return tree[x].parent;
}
else
{
return x;
}
} void DisJoinSet::Union(int x,int y)
{
int pa = Find(x);
int pb = Find(y);
if(pa == pb)return ;
else
{
tree[pa].parent = pb;//x的根变为y的根 即把x所在的堆放在y所在的堆上面
under[pa] = total[pb];//pa下的数量即原来y所在栈里的元素total
total[pb] += total[pa];//更新y的totoal
}
} int main()
{
int p;
while(scanf("%d",&p) != EOF)
{
if(p == )break;
DisJoinSet dis(p);
char s1[];
for(int i = ;i < p ;i++)
{ int s2;
int s3;
scanf("%s",s1);
if(s1[] == 'M')
{
scanf("%d%d",&s2,&s3);
int pa = dis.Find(s2);
int pb = dis.Find(s3);
if(pa != pb)
{
dis.Union(s2,s3);
}
}
if(s1[] == 'C')
{
scanf("%d",&s2);
dis.Find(s2);
cout<<under[s2]<<endl;
}
}
dis.~DisJoinSet();
}
return ;
}

POJ1988(Cube Stacking)--并查集的更多相关文章

  1. poj.1988.Cube Stacking(并查集)

    Cube Stacking Time Limit:2000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64u Submi ...

  2. poj1988 Cube Stacking 带权并查集

    题目链接:http://poj.org/problem?id=1988 题意:有n个方块,编号为1-n,现在存在两种操作: M  i  j  将编号为i的方块所在的那一堆方块移到编号为j的方块所在的那 ...

  3. POJ1988 Cube Stacking 【并查集】

    题目链接:http://poj.org/problem?id=1988 这题是教练在ACM算法课上讲的一道题,当时有地方没想明白,现在彻底弄懂了. 题目大意:n代表有n个石头,M a, b代表将a石头 ...

  4. poj1988 Cube Stacking(并查集

    题目地址:http://poj.org/problem?id=1988 题意:共n个数,p个操作.输入p.有两个操作M和C.M x y表示把x所在的栈放到y所在的栈上(比如M 2 6:[2 4]放到[ ...

  5. poj1988 Cube Stacking

    并查集的高效之处在于路径压缩和延迟更新. 在本题中需要额外维护子树的规模以及当前子树节点到跟的距离两个数组. 由于一个新的数必然是两棵树拼接而成,对于子树规模的更新直接相加即可, 对于节点到跟的距离: ...

  6. POJ1988 Cube stacking(非递归)

    n有N(N<=30,000)堆方块,开始每堆都是一个方块.方块编号1 – N. 有两种操作: nM x y : 表示把方块x所在的堆,拿起来叠放到y所在的堆上. nC x : 问方块x下面有多少 ...

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

    题目链接:id=1988">POJ 1988 Cube Stacking 并查集的题目 [题目大意] 有n个元素,開始每一个元素自己 一栈.有两种操作,将含有元素x的栈放在含有y的栈的 ...

  8. bzoj3376/poj1988[Usaco2004 Open]Cube Stacking 方块游戏 — 带权并查集

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3376 题目大意: 编号为1到n的n(1≤n≤30000)个方块正放在地上.每个构成一个立方 ...

  9. POJ 1988 Cube Stacking( 带权并查集 )*

    POJ 1988 Cube Stacking( 带权并查集 ) 非常棒的一道题!借鉴"找回失去的"博客 链接:传送门 题意: P次查询,每次查询有两种: M x y 将包含x的集合 ...

随机推荐

  1. VSCode 代码格式化 快捷键

    Visual Studio Code可以通过以下快捷键 格式化代码: On Windows  Shift + Alt + F On Mac  Shift + Option + F On Ubuntu ...

  2. 利用redis实现分布式事务锁,解决高并发环境下库存扣减

    利用redis实现分布式事务锁,解决高并发环境下库存扣减   问题描述: 某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖 解决方案一 利用数据 ...

  3. Python之queue模块以及生产消费者模型

    队列 队列类似于一条管道,元素先进先出,进put(arg),取get() 有一点需要注意的是:队列都是在内存中操作,进程退出,队列清空,另外,队列也是一个阻塞的形态. 队列分类 队列有很多中,但都依赖 ...

  4. Python的Asyncore异步Socket模块及实现端口转发的例子

    Python的Asyncore异步Socket模块及实现端口转发的例子 Asyncore模块提供了以异步的方式写入套接字服务客户端和服务器的基础结构. 只有两种方式使一个程序在单处理器上实现" ...

  5. cursor -- 定义鼠标样式

    cursor -- 定义鼠标样式 取值: [ [<uri> ,]* [ auto | crosshair | default | pointer | move | e-resize | n ...

  6. React16+配置打包目录

    在学习react的时候,肯定最终都要用脚手架,对比了手写配置webpack(比较费劲).generator-react-webpack(打不开官方文档……),最终还是选择了react官方的create ...

  7. dropout含义与原理

    含义 在训练过程中,对神经网络单元按照一定比例暂时将其丢弃. 原理 由于网络参数过多,训练数据少,或者训练次数过多,会产生过拟合的现象.dropout产生的一个重大原因就是为了避免过拟合. 每一层的神 ...

  8. c#,绝对值

    Console.WriteLine("输入任意整数"); var n = int.Parse(Console.ReadLine()); var num = Math.Abs(n); ...

  9. 工作总结--CTO(张王岩)File的使用

    名称     路径分隔符 pathSeparator   separator 构造器 文件名.路径名 getName()  getPath() getAbsolutePath()  getParent ...

  10. 第一周----常量和final

    符号常量   final 字面常量:1 2 int  a=3;   a是变量   3是常量