Kruskal 重构树

这是一种用于处理与最大/最小边权相关的一个数据结构。

其与 kruskal 做最小生成树的过程是类似的,我们考虑其过程:

按边权排序,利用并查集维护连通性,进行合并。

如果我们在合并时,新建一个节点,其权值为当前处理的边的权值,并将合并的两个节点都连向新建的节点,那么就可以得到一颗重构树。

例如下列数据生成的重构树:

4
1 4 2
2 3 4
1 3 1
3 4 3

黑色代表节点编号,红色代表其权值。

其满足一些性质:

  • 这是一个二叉树,也是一个二叉堆

  • 两点 \(\mathrm{LCA}\) 的权值即是这两点联通的 最小/最大 代价/时间。

  • 对于一个限制,找到某个点最高的祖先 \(S\) 满足这个限制,那么 \(S\) 所在子树都满足此限制,并且此子树下所有叶节点在此限制下全部联通。

由于这些性质,kruskal 重构树常常与树剖/树上倍增放一起,做到每次 \(O(\log n)\) 的神秘操作。


Qpwoeirut and Vertices - 洛谷 为例:

给出 \(n\) 个点,\(m\) 条边的不带权无向连通图,\(q\) 次询问至少要加完前多少条边 \([L, R]\) 中的所有节点联通。

这是非常板的题,边权也就是其编号。

设 \(f(x)\) 表示 \(x\) 和 \(x + 1\) 联通的时间,那么所求也就是 \(\max_{x = L}^{R - 1} f(x)\),这只需要求出 \(f(x)\) 随便维护一下即可。

那么求 \(x, x + 1\) 的联通时间,找到他们在重构树上的 \(\mathrm{LCA}\),返回其编号即可。


[NOI2018] 归程 - 洛谷

或许其考点就是知不知道重构树,如果会了重构树,那么就简单了。

按照边权从大到小建出重构树,那么在当前水位下可联通的部分(整棵子树)也就很好求。

求这部分到固定的终点的最短路径?跑一次 DJK,然后把重构树看作一颗线段树,节点保存的也就是子树内最小的距离,在查询的时候利用倍增跳一跳就行了。


另一种打开方式 - 基于点权的 kruskal 重构树

我们从这道题开始:

给定一颗树,认为一条从 \(x \to y\) 的简单路径是好的,当且仅当路径上的点中编号最小的是 \(x\),最大的是 \(y\)。计数好的简单路径条数。

有一种解决方法是利用笛卡尔树,然而我并不是很会,所以不管了。

这里发现没有我们熟悉的边权了,但是我们仍然可以考虑类似的过程,首先按照点权排序,这里不妨设为从小到大。

那么我们依次遍历 \(x\),如果此时遍历到了一个边 \((x, y)\) 满足 \(w_x > w_y\),那么将 \(x\) 作为 \(y\) 所在的树的根的父亲(也就是并查集合并的过程,合并完之后其实就是一个重构树)

可以发现,这样,\(\mathrm{lca}(x, y)\) 的点权也就是原树上两点路径间的最大权值。

同理,在这道题中建出从大到小的树,那么 \((x, y)\) 能够做出贡献当且仅当在一棵树上 \(x\) 作为 \(y\) 的祖先,并且在另外一颗树上 \(y\) 是 \(x\) 的祖先。

于是在一棵树上加,另一棵树上遍历即可。

# [IOI2018] werewolf 狼人

我们通过这道经典的题目细致的讲一讲如何构造点权的重构树。

题意中的路径需要满足前面部分 \(\ge L_i\),后面部分 \(\le R_i\),我们按照点编号大小构建两棵重构树,第一棵是最小联通标号,第二则是最大。

这是原树:

我们先构造第一棵,也就是最小联通标号,那么此时我们需要从编号大的作为叶子开始,一点一点构建这个树。

首先加入 \(5\) 节点,没有已经加入的节点,则加入 \(4\),同理,则加入 \(3\),发现此时 \(4\) 存在,并且其所在树的根为 \(4\),则将 \(3\) 作为 \(4\) 的根:

此时继续加入 \(2\),没有连着已经加入的节点,继续加入 \(1\),发现 \(1\) 与 \(5, 2, 3\) 相连,那么将 \(1\) 作为他们所在子树的根即可:

最后加入 \(0\),发现与 \(3\) 相连,则 \(0\) 作为 \(3\) 所在的子树的根的父亲即可:

此时,我们构造出的这棵重构树满足两点的 \(lca\) 即他们在原树上路径间的最小值,除了不是一棵二叉树,性质与边权重构的树性质类同。

同理,我们可以构造出另一棵树:

于是问题转化为在求两棵树上两个子树是否有交,这不是本文的重点,略。

这部分的代码大概就是:

mfs.init(n);
for (int x = 0; x < n; ++x) {
for (int y : T[0].G[x]) {
// 如果还没有加入或者已经联通就跳过
if (y > x || mfs.find(x) == mfs.find(y)) continue;
T[1].add(x, mfs.find(y)); // 注意这里是 x 作为 find(y) 的父亲!
mfs.merge(y, x); // 注意这里是 grp[find(y)] = x !!!
}
}

然而事实上我们可以不用如此,完全可以直接将点权下方到边权即可。

在这道题来说,如果是构建第一棵树,那么边权设为 \(\min(x, y)\) 即可。

构造出来的树即是:

可以看见构建顺序不同……但是很像!就是把相同的点缩起来了……QwQ

不过感觉第一种写法在处理一些东西的时候方便很多。


作者有话说

对于重构树的另一种打开方式我并没有在其他地方看到过,毕竟它并没有什么特别突出的点使得它可以代替边权的重构树,甚至在重构出来的形态 - 非二叉树上劣于边权的重构树。

不过这个思想还是蛮不错的。

有总比没有的好

算法学习笔记(30):Kruskal 重构树的更多相关文章

  1. 【学习笔记】Kruskal 重构树

    1. 例题引入:BZOJ3551 用一道例题引入:BZOJ3551 题目大意:有 \(N\) 座山峰,每座山峰有他的高度 \(h_i\).有些山峰之间有双向道路相连,共 \(M\) 条路径,每条路径有 ...

  2. 学习笔记:Kruscal 重构树

    网上感觉没有什么很详细 + 证明的讲解啊) 前置:Kruskal 求最小生成树. 这个算法可以将一棵树 / 无向连通图重构成一颗有性质的新树. 算法可以解决一些树上瓶颈边权之类的问题,可以把需要持久化 ...

  3. kruskal重构树学习笔记

    \(kruskal\) 重构树学习笔记 前言 \(8102IONCC\) 中考到了,本蒟蒻不会,所以学一下. 前置知识 \(kruskal​\) 求最小(大)生成树,树上求 \(lca​\). 算法详 ...

  4. Kruskal重构树学习笔记+BZOJ3732 Network

    今天学了Kruskal重构树,似乎很有意思的样子~ 先看题面: BZOJ 题目大意:$n$ 个点 $m$ 条无向边的图,$k$ 个询问,每次询问从 $u$ 到 $v$ 的所有路径中,最长的边的最小值. ...

  5. [学习笔记]kruskal重构树 && 并查集重构树

    Kruskal 重构树 [您有新的未分配科技点][BZOJ3545&BZOJ3551]克鲁斯卡尔重构树 kruskal是一个性质优秀的算法 加入的边是越来越劣的 科学家们借这个特点尝试搞一点事 ...

  6. 算法学习——kruskal重构树

    kruskal重构树是一个比较冷门的数据结构. 其实可以看做一种最小生成树的表现形式. 在普通的kruskal中,如果一条边连接了在2个不同集合中的点的话,我们将合并这2个点所在集合. 而在krusk ...

  7. [算法模板]Kruskal重构树

    [算法模板]Kruskal重构树 kruskal重构树是一个很常用的图论算法.主要用于解决u->v所有路径上最长边的最小值,就是找到\(u->v\)的一条路径,使路径上的最长边最小. 图片 ...

  8. [luogu P4197] Peaks 解题报告(在线:kruskal重构树+主席树 离线:主席树+线段树合并)

    题目链接: https://www.luogu.org/problemnew/show/P4197 题目: 在Bytemountains有N座山峰,每座山峰有他的高度$h_i$.有些山峰之间有双向道路 ...

  9. 【BZOJ】3732: Network【Kruskal重构树】

    3732: Network Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2812  Solved: 1363[Submit][Status][Dis ...

  10. 【NOI 2018】归程(Kruskal重构树)

    题面在这里就不放了. 同步赛在做这个题的时候,心里有点纠结,很容易想到离线的做法,将边和询问一起按水位线排序,模拟水位下降,维护当前的各个联通块中距离$1$最近的距离,每次遇到询问时输出所在联通块的信 ...

随机推荐

  1. 力扣665(java)-非递减数列(中等)

    题目: 给你一个长度为 n 的整数数组 nums ,请你判断在 最多 改变 1 个元素的情况下,该数组能否变成一个非递减数列. 我们是这样定义一个非递减数列的: 对于数组中任意的 i (0 <= ...

  2. 力扣554(java&python)-砖墙(中等)

    题目: 你的面前有一堵矩形的.由 n 行砖块组成的砖墙.这些砖块高度相同(也就是一个单位高)但是宽度不同.每一行砖块的宽度之和相等. 你现在要画一条 自顶向下 的.穿过 最少 砖块的垂线.如果你画的线 ...

  3. 为什么Spring仍然会是云原生时代最佳平台之一?

    简介: 基于Java语言的Spring生态,还能否适应新的开发方式,比如Cloud Native.Serverless.Faas等,它还会是云原生时代的最佳平台的选择吗?本文将从5个角度来为你分析一下 ...

  4. [FE] uViewUI u-navbar 曲线解决 uni onNavigationBarButtonTap 的限制与失效

    uni 自带的 navigation bar 对于普通的导航需求是够用的,也允许 onNavigationBarButtonTap 加点击事件. 但是会出现异常Bug,表现为在内部页面一番操作后,再返 ...

  5. dotnet 在 UOS 统信系统上运行 UNO 程序输入时闪烁黑屏问题

    本文记录我在虚拟机内安装了 UOS 统信系统,运行 UNO 的基于 Skia 的 Gtk 应用程序时,在输入的过程中不断窗口闪黑问题 本质上说这个问题和 UNO 毫无关系,这是一个 OpenGL 硬件 ...

  6. dotnet 6 命令行 cmd 设置输出英文解决中文乱码

    我遇到在部署 CI 服务器,执行 cmd 命令构建,输出的中文是乱码.我期望让 dotnet 命令行输出使用英文解决乱码问题.通过设置 dotnet 命令行的语言文化,即可解决此问题 给 dotnet ...

  7. redis-desktop-manager-0.8.0.3844

    redis-desktop-manager-0.8.0.3844 下载地址: https://www.aliyundrive.com/s/Y2fobkVjAdF 链接:https://pan.baid ...

  8. gorm 动态拼接查询条件

    结构体 type Mould struct { MouldId string `grom:"column:mouldID"` MouldInteriorID string `gro ...

  9. Golang validate验证器

    目录 自定义验证规 单条验证 多条批量验证 其它验证包: gookit/validate 手册地址: https://godoc.org/gopkg.in/go-playground/validato ...

  10. ansible系列(1)--ansible基础

    目录 1. ansible概述 1.1 ansible的功能 1.2 ansible的特性 1.3 ansible的架构 1.4 ansible注意事项 1. ansible概述 Ansible 是一 ...