首页 > 代码库 > Kruskal重构树

Kruskal重构树

不支持时间旅行的可持久化并查集

  给定 n 个点, 以及 m 次操作, 操作有两种:

    ① 将点 x 与点 y 进行连边;

    ② 询问在前 t 次操作操作中, x 与 y 是否连通.

  n <= 100000, 强制在线.

 

核心模型

  n 个点, m 条带权边的无向图.

  多次询问点 x 和点 y 在边权不超过 w 的边的作用下的连通性信息(例如, 是否连通).

  强制在线.

 

  对于不支持时间旅行的并查集问题, 将时间这一维给量化之后, 可以等价地看成这个核心模型.

  对于操作①, 我们相当于连边 (x, y) , 边权为 t .

  对于操作②, 相当于查询边权不超过 t 的边的作用下, x 和 y 是否连通.

 

问题解决

  假如可以离线, 那么我们就有 Kruskal + 并查集 的做法.

  从小到大, 每连接一条边, 就将连接下一条边前的询问进行回答.

 

  现在要求在线, 我们尝试维护历史版本的并查集.

  我们考虑在并查集存储更多的信息, 从而也使用更适合的按秩合并的方法, 而不使用更快的路径压缩的方法.

  将点 x 的父亲设为 y 的时候, 我们考虑多记录 w 数组, w[x] = 当前连边的边权.

 

  我们当前要查找在不超过 d 的边权的作用下, x 在并查集的代表元素.

  我们从查询的点开始跳, 当且仅当 d >= w[x] , 那么代表元素是 x 的祖先.

  如此下来, 我们能找到并查集的代表元素, 且复杂度为 O(n log n) .

 

Kruskal重构树

  我们把利用 f[], w[] 两个数组构建出来的树叫做 Kruskal重构树 .

  我们可以轻易地查询在边权不超过 d 的边的作用下, x 对应的并查集的代表元素 a . 我们还可以知道更多的信息, 因为与 x 连通的元素的集合就是 a 的子树对应的集合.

  所以, 这棵树的作用可以概括为: 询问 x 在边权不超过 d 的边的作用下的连通性信息.

 

  以强制在线 Peaks 一题为例.

  给定一张图, m 次询问 (x, k): 在边权不超过 d 的边的作用下, 与 x 连通的所有点中点权第 k 小是多少?

  我们考虑利用并查集构建出 Kruskal 重构树, 我们找边权不超过 d 的边的作用下, x 的代表元素 a , 那么相当于查询子树 a 的所有点的点权第 k 小.

Kruskal重构树