POJ1988 Cube Stacking 【并查集】
题目链接:http://poj.org/problem?id=1988
这题是教练在ACM算法课上讲的一道题,当时有地方没想明白,现在彻底弄懂了。
题目大意:n代表有n个石头,M a, b代表将a石头所在的集合放在b石头所在的所有集合的上方。C a代表询问a石头下方有多少个石头。
思路:
1.一开始我是想用一个 num 数组来表示每块石头下方有多少个石头,然后直接用并查集来写,但是发现最终不能实现,因为只用一个num数组只能保证每个集合的最顶端的石头num值是正确的。
2.正解是用一个 dis 数组代表每块石头到根节点石头的距离,num数组代表每块石头所在集合的石头总数,最终答案就是 num[find(a)] - dis[a] - 1;
3.需要注意的地方是 先查找根节点 后更新dis以及num,因此在查询某一块石头下面有多少石头时,还需要进行一次 find 来更新一下路径上石头的dis。
代码里的注释写的很详细
代码:
注意:数据好像比题面给的大,数组要开大点。
#include<iostream> //用cin输入无视空格和回车,方便判断操作
using namespace std; int num[], pre[], dis[]; int find(int x)
{
if(pre[x] == x)
return x;
else
{
int root = find(pre[x]);
dis[x] += dis[pre[x]];//下面的块中点到新根节点的距离为 原来的距离dis[x]加上被更新过的dis[root] = num[x]的距离
pre[x] = root;
return pre[x];
}
} int main()
{
cin.sync_with_stdio(false);//关闭cin同步加速,但读入只能用cin了
int n;
cin >> n;
for(int i = ; i <= n; i ++)
{
pre[i] = i;
dis[i] = ;//到根节点的距离
num[i] = ;//每个块中包含的点数目
}
while(n --)
{
char ch;
cin >> ch;
if(ch == 'M')
{
int a, b;
cin >> a >> b;
int x = find(a), y = find(b);//此时的find只是找到根节点,find()函数中各点dis值没有改变,因为此时根节点的dis为0
if(x != y)
{//注意顺序
dis[y] = num[x];//这里才给根节点的dis值进行了更新,所以下次还需要调用一次find才能维护各点的dis值
num[x] += num[y];//以x为根节点的块中数目更新为 以x和y为根节点的两个块中点的数目之和
pre[y] = x;
}
}
else if(ch == 'C')
{
int a;
cin >> a;
int x = find(a);//查询之前还需要进行一次 find 来更新块中各点的dis值
printf("%d\n", num[x] - dis[a] - );
}
}
return ;
}
POJ1988
POJ1988 Cube Stacking 【并查集】的更多相关文章
- POJ1988(Cube Stacking)--并查集
题目链接:http://poj.org/problem?id=1988 题意:有n个元素,开始每个元素各自在一个栈中,有两种操作,将含有元素x的栈放在含有y的栈的顶端,合并为一个栈. 第二种操作是询问 ...
- poj.1988.Cube Stacking(并查集)
Cube Stacking Time Limit:2000MS Memory Limit:30000KB 64bit IO Format:%I64d & %I64u Submi ...
- poj1988 Cube Stacking 带权并查集
题目链接:http://poj.org/problem?id=1988 题意:有n个方块,编号为1-n,现在存在两种操作: M i j 将编号为i的方块所在的那一堆方块移到编号为j的方块所在的那 ...
- poj1988 Cube Stacking(并查集
题目地址:http://poj.org/problem?id=1988 题意:共n个数,p个操作.输入p.有两个操作M和C.M x y表示把x所在的栈放到y所在的栈上(比如M 2 6:[2 4]放到[ ...
- poj1988 Cube Stacking
并查集的高效之处在于路径压缩和延迟更新. 在本题中需要额外维护子树的规模以及当前子树节点到跟的距离两个数组. 由于一个新的数必然是两棵树拼接而成,对于子树规模的更新直接相加即可, 对于节点到跟的距离: ...
- POJ1988 Cube stacking(非递归)
n有N(N<=30,000)堆方块,开始每堆都是一个方块.方块编号1 – N. 有两种操作: nM x y : 表示把方块x所在的堆,拿起来叠放到y所在的堆上. nC x : 问方块x下面有多少 ...
- POJ 1988 Cube Stacking(并查集+路径压缩)
题目链接:id=1988">POJ 1988 Cube Stacking 并查集的题目 [题目大意] 有n个元素,開始每一个元素自己 一栈.有两种操作,将含有元素x的栈放在含有y的栈的 ...
- bzoj3376/poj1988[Usaco2004 Open]Cube Stacking 方块游戏 — 带权并查集
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3376 题目大意: 编号为1到n的n(1≤n≤30000)个方块正放在地上.每个构成一个立方 ...
- POJ 1988 Cube Stacking( 带权并查集 )*
POJ 1988 Cube Stacking( 带权并查集 ) 非常棒的一道题!借鉴"找回失去的"博客 链接:传送门 题意: P次查询,每次查询有两种: M x y 将包含x的集合 ...
随机推荐
- Codevs 1574 广义斐波那契数列(矩阵乘法)
1574 广义斐波那契数列 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 广义的斐波那契数列是指形如an=p*an-1+q* ...
- Appium基础教程
目录 Appium教程 Appium简介 App自动化测试工具对比 Appium实现原理 环境搭建 Andorid介绍 基本架构 常见布局/视图 基本控件 控件常见属性 Adb介绍 Adb常用命令 A ...
- 在eclipse中查找一个类中的方法在其他哪个类中被调用了
选中你所要查看的方法名,ctrl+shift+G就可以查看所有调用过该方法的地方了.在Search视图里面可以查看得到这个样子是可以的,你也可以按Ctrl+H全文检索一下
- codeforces#999 E. Reachability from the Capital(图论加边)
题目链接: https://codeforces.com/contest/999/problem/E 题意: 在有向图中加边,让$S$点可以到达所有点 数据范围: $ 1 \leq n \leq 50 ...
- JavaWeb_(Spring框架)Spring配置文件
一.什么是spring IOC IOC(Inversion of Control)即控制反转,在我们以往的编程中如果需要一个bean往往需要去手动去new一个出来.而spring帮我们解决了这个问题, ...
- fastadmin编辑内容,有下拉选择关联的内容,自定义的参数去获取相应的下拉内容
1.可以到你的编辑页面中添加自定义条件 data-params='{"custom[shop_id]":"2"}'
- springboot内置分页技术
1,在pom.xml中注入分页的配置 <dependency> <groupId>com.github.pagehelper</groupId> <artif ...
- 如何使用git send-email发送补丁?
答: git send-email <patch-name> --to <username>@<example>.com --cc <username> ...
- BrowserUtils
import android.content.Context; import android.content.Intent; import android.net.Uri; public class ...
- Django博客系统
零.创建项目及配置 一.编写 Model 层的代码 二.配置 admin 页面 三.根据需求定制 admin