0
点赞
收藏
分享

微信扫一扫

次小生成树

逸省 2022-04-07 阅读 61
算法

前言

在 亲 爱 的 马 基 佬 的 要 求 下 没 有 贴 代 码 \color{white}{在亲爱的马基佬的要求下没有贴代码} (((

额 我也不知道为什么要发出来以及为什么要起这个标题 大概是因为好玩吧。

总码长 3.5k。然而在码到 3.2k 的时候 cindy 走过来顺手把我电脑关了。

曾经我也想过一了百了,但是好在我在码了 2.7k 的时候顺手备份了一下。

正文

Description

给定 N N N 个点, M M M 条边,求 严格 次小生成树。

严格次小生成树的定义:边权和最小的满足边权和 严格大于 最小生成树边权和的生成树。

Solution

我们来捋一下整道题的思路。

  1. 最小生成树

    看到次小生成树,许多人都会联想到最小生成树。

    相信大家都会用 Kruskal 算法求解最小生成树。所以这一步我们跳过。

  2. 不严格次小生成树

    如何把最小生成树 M M M 转换为不严格次小生成树 M ′ M' M

    对于任意一条 不存在于 M M M 中的 ( u , v , w ) (u,v,w) (u,v,w),我们将其加入最小生成树。

    此时的最小生成树已经不是树了,因为它有 n n n 个点, n n n 条边。也就是说,图中一定存在至少一个环。删除这个环上的任意一条边,图还原为树。

    这个环是在加入边 ( u , v , w ) (u, v, w) (u,v,w) 后产生的,所以点 u u u 和点 v v v 一定在环上。

    显然,令 t = lca ⁡ ( u , v ) t=\operatorname{lca}(u,v) t=lca(u,v),则这个环由原生成树上两条简单路径 u → t u\to t ut v → t v\to t vt 和边 ( u , v , w ) (u,v,w) (u,v,w) 组成。

    为了让图还原为树,我们需要删除这个环上的边。这条边不能是我们刚刚加入最小生成树的边 ( u , v , w ) (u, v, w) (u,v,w),因为我们要用它尝试让最小生成树的权值变大;所以我们就只能在 u → t u\to t ut v → t v\to t vt 中选择。

    我们找到 u → t u\to t ut v → t v\to t vt 上权值最大的边,用 ( u , v , w ) (u, v, w) (u,v,w) 替换,就能得到不严格次小生成树。

    在使用倍增法维护最小生成树的 LCA 的同时,我们维护一个最大值数组 p p p,其定义与倍增祖先数组 f f f 的定义类似:p[i][j] 表示点 i i i 向上(树根方向)的 2 j 2^j 2j 条边中,边权的最大值。

    其转移则类似于 ST 表求 RMQ:

    for(int j = 1; j <= 20; ++j) {
        f[i][j] = f[f[i][j-1]][j-1];
        p[i][j] = max (p[i][j-1], p[f[i][j-1]][j-1]);
    }
    

    于是我们可以轻松地得到路径上的最大边权 w ′ w' w,则最后的答案为 M ′ = M − w ′ + w M'=M-w'+w M=Mw+w

    比较对于所有边生成的 M ′ M' M,取其最小值为答案,因为 M ′ M' M 必须满足在所有可生成的树中,除了 M M M 权值最小。

  3. 严格次小生成树

    我们思考,不严格次小生成树操作过程中的哪一步使得其不严格?其实就是因为 w ′ w' w 可能与 w w w 相等。

    我们专门针对这个问题处理,同时记录 u → t u\to t ut v → t v\to t vt 中的最大值和 严格 次大值,当最大值与 w w w 相等时,就弃用最大值,使用次大值。严格次大值的维护方法与最大值类似。

以及,我绝对没有模仿某个帖子。绝对没有。

举报

相关推荐

0 条评论