并查集——poj1988(带权并查集中等)
一、题目回顾
题目链接:Cube Stacking
题意:有n个箱子,初始时每个箱子单独为一列;接下来有p行输入,M, x, y 或者 C, x;
- 对于M,x,y:表示将x箱子所在的一列箱子搬到y所在的一列箱子上;
- 对于C,x:表示求箱子x下面有多少个箱子;
输出:在箱子x所在的那列中,求出在x之下的cube的个数。
二、解题分析
知识点:带权并查集
解题思路
- 初级:M x y是将x所在列的所有箱子叠到y所在列的上面,如果直接模拟的话就是将x最末端的叶子节点当做y的根节点的父亲节点合并,不过那样的话不好压缩路径,不压缩路径的话会超时.......
- 高级:用数组s存储当前节点x的子结点数量,用数组d存储当前节点到根节点的距离,所求值即s[find(x)]-d[x],(也许你会说要求的不就是s[x]吗,道理是这样,但我们并没有求出每个节点的子结点数量)
- 续上高级:按照一般并查集的合并方法,令pre[find(y)]=find(x);那合并后会有: d[find(y)]=s[find(x)]+1,s[find(x)]+=s[find(y)]+1 。(不清楚可以自己在草稿纸上画图确定)
重要之处
- 多了两个结点之间的关系
- d[x]表示结点x到根的距离
- s[x]表示在结点x下cube的数量
- 然后在find函数、unite函数内维持这两个数组即可
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int p;
int pre[];
int d[]; //d[x]表示结点x到根的距离
int s[]; //s[x]表示在结点x下cube的数量
void init()
{
for(int i=;i<=;i++){
pre[i] = i;
// d[i] = 0; 加上这个就 WA
s[i] = ;
}
} int find(int x)
{
if(x==pre[x]) return x;
int t = pre[x]; //***递归思想,t为存储x改变根节点后的根节点的临时变量
pre[x] = find(pre[x]);
d[x] = d[x] + d[t]; //***x到改变前根节点的距离即x到t的距离加上t到根节点的距离
return pre[x];
} void unite(int x,int y)
{
int fx = find(x);
int fy = find(y);
if(fx != fy){
pre[fy] = fx;
//***将x所在列放到y所在列上面后,find(y)到新合并后的根节点的距离即为合并前find(x)的子树的大小
d[fy] = s[fx]+;
s[fx] = s[fx]+(s[fy]+); //***合并后find(x)的子树大小即为合并前find(x)与find(y)的子树大小的和
}
} int main()
{ cin>>p;
init();
char ch; int x,y;
getchar();
while(p--){
scanf("%c",&ch);
if(ch=='M'){
scanf("%d%d",&x,&y);
unite(x,y);
}
if(ch=='C'){
scanf("%d",&x);
//***注意这里并不是输出son(x),因为我们并没有求出每个节点的子树的大小
printf("%d\n",s[find(x)]-d[x]);
}
getchar();
}
return ;
}
并查集——poj1988(带权并查集中等)的更多相关文章
- BZOJ4025 二分图 分治 并查集 二分图 带权并查集按秩合并
原文链接http://www.cnblogs.com/zhouzhendong/p/8683831.html 题目传送门 - BZOJ4025 题意 有$n$个点,有$m$条边.有$T$个时间段.其中 ...
- 并查集模板 && 带权并查集模板
不带权: ]; void init(void) { ;i<=n;i++) f[i]=i; } int fd(int x) { return f[x]==x?x:fd[x]=fd(f[x]); } ...
- hdu 2818(并查集,带权更新)
Building Block Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- LA 6187 - Never Wait for Weights 并查集的带权路径压缩
只有一个地方需要注意: 设节点a的根为u,b的跟为v,则:a = u + d[a]; b = v + d[b]; 已知:b-a=w.所以v - u = d[a] - d[b] + w; 在合并两个集 ...
- 浅谈并查集&种类并查集&带权并查集
并查集&种类并查集&带权并查集 前言: 因为是学习记录,所以知识讲解+例题推荐+练习题解都是放在一起的qvq 目录 并查集基础知识 并查集基础题目 种类并查集知识 种类并查集题目 并查 ...
- bzoj3376/poj1988[Usaco2004 Open]Cube Stacking 方块游戏 — 带权并查集
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3376 题目大意: 编号为1到n的n(1≤n≤30000)个方块正放在地上.每个构成一个立方 ...
- POJ1988(带权并查集,搬砖块)
题意: 可以这样理解,有n快方形积木,一开始都是单独的放到哪,然后有两种操作 1 M a b 把a所在的那一堆落到b所在那一堆的上面(一开始自己是一堆) 2 C a 问a下面有多少个积木 ...
- POJ 1988 Cube Stacking( 带权并查集 )*
POJ 1988 Cube Stacking( 带权并查集 ) 非常棒的一道题!借鉴"找回失去的"博客 链接:传送门 题意: P次查询,每次查询有两种: M x y 将包含x的集合 ...
- POJ 1703 Find them, Catch them(带权并查集)
传送门 Find them, Catch them Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 42463 Accep ...
随机推荐
- html 固定长度 超出长度 显示省略号
a{ width: 80px;/* 要显示文字的宽度 */ float: left;/* 左对齐,不设置的话只在IE下好用 */ overflow: h ...
- 课时59.体验css(理解)
我们想做这样一个样式,应该怎么做? 分析: 有一个标题(h1),还有一些段落(p) 标题是居中的,段落也是居中的,所以我们可以设置h标签和p标签居的align属性等于center来实现 标题和段落都有 ...
- SpringBoot非官方教程 | 第十七篇:上传文件
转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springboot/2017/07/11/springboot14-upload/ 本文出自方志朋的博客 这篇文 ...
- oracle-sql脚本导出EXCEL数据
在数据库中,经常有业务人员提出需求导出数据库中的业务数据,而且是每天.每周或每月定时导出.为了方便,可将sql查询的脚本 通过下面脚本来导出EXCEL数据. 1.将查询sql脚本(AAA.sql)放到 ...
- c# 分析SQL语句中的表操作
最近写了很多方向的总结和demo.基本包含了工作中的很多方面,毕竟c#已经高度封装并且提供了很多类库.前面已经总结了博文.最近2天突然感觉前面的SQL分析阻组件的确麻烦,也注意看了下.为了方便大家学习 ...
- Integer大小比较问题
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Integer ...
- union的两个子查询是否并行
需求描述 问题:subquery 1 union subquery2,其中union左右的两个子查询是否并行. 场景:业务中性能敏感的业务,希望能加快速度,如果数据库能两个子查询并行执行,既可以节省时 ...
- 蓝图(Blueprint)详解
Blueprint 模块化 随着flask程序越来越复杂,我们需要对程序进行模块化的处理,针对一个简单的flask程序进行模块化处理 举例来说: 我们有一个博客程序,前台界面需要的路由为:首页,列表, ...
- ZooKeeper(2)-安装和配置
一.下载 https://zookeeper.apache.org/ 二.本地模式安装 1.安装前准备 (1)安装Jdk (2)拷贝Zookeeper安装包到Linux系统下 (3)解压到指定目录 . ...
- PAT-A1002
1002 A+B for Polynomials (25) Polynomials多项式,exponents指数,coefficients系数 输入:两行数据,每行表示一个多项式:第一个数字表示非零项 ...