• Complete the MST 题解


    一、前言

    截至目前,这是练习的第一道完全没有听别人提示的题。hh


    二、题解

    Hint 1:

    首先没有确定边权的边,边权分配一定是一条边的权值为 r e t = v a l 1 ⨁ v a l 2 . . . ⨁ v a l m ret = val_1 \bigoplus val_2 ... \bigoplus val_m ret=val1val2...valm,其余边的边权为 0。
    因为这样分配只有未确定边全选的情况才会贡献 ret,而其他分配方式除此情况提供 ret 的贡献,还一定会在一些选择方式中提供贡献,所以这样的分配方式可以以不变应万变。


    Hint 2:

    如果没有确定边权的边的数量 (number_uncertain) 大于了 n - 1,那么最小生成树中没有确定边权的边的权值一定为 0。
    因为生成树的边数为 n - 1,一定有一个没有确定边权的边没有用到,让他的权值为 ret 就行了。


    Hint 3:

    根据 Kruskal 算法,我们会从边权小的边开始考虑选择,所以我们可以先连边权为 0 的边。


    根据上面的三个 Hint,我们可以有如下的解法。

    情况1 : n u m b e r _ u n c e r t a i n > n − 1 number\_uncertain > n - 1 number_uncertain>n1

    Boruvka 算法。
    s[u] 记录以 u 为根的并查集的不能相连的点的编号。
    并查集合并时用按秩合并,在较小的并查集里删除不存在于大并查集里的元素。
    连通块向外连边时,对于该连通块打一个不可选的编号的表,随便选择一个可选的点,可以考虑每个不可选的编号的相邻编号(因为这种选法和全部遍历选择的存在性是等价的)。
    时间复杂度均摊下来是 O ( l o g 2 V ( V + E ) ) O (log_2V (V + E)) O(log2V(V+E))

    这样我们将所有的边权为零的边连好了,然后在连好的图上跑一个 Kruskal 就行了。

    情况2 : n u m b e r _ u n c e r t a i n ≤ n − 1 number\_uncertain \leq n - 1 number_uncertainn1

    这时点的个数不超过 1000 1000 1000 (上界但不是上确界),可以将未确定的边的边权设为 0 跑一个 kruskal,如果未确定的边全部属于 MST 中,那么枚举任意两个点,连接后在形成的环上去掉一个边权为 0 的边(如果没有边权为 0 的边则不能有这样的生成树)。
    注意 1: 不要忘了让一个未确定边的边权为 ret 的生成树
    注意 2: 实际计算时并不需要连接删边的操作,这样的描述仅便于理解。


    代码

  • 相关阅读:
    lnx和ln|x|
    [附源码]java毕业设计电影影评网
    Activiti进阶
    前端研习录(21)——JavaScript循环语句合集
    【笔试强训】Day1
    约瑟夫环问题——《算法》1.1.37的解法
    JAVA基础——day04
    X METAVERSE PRO Launches Cloud Mining, Creating a “New Era of Mining Trend”
    个人笔记-随意记录
    Python之pandas库--基础
  • 原文地址:https://blog.csdn.net/C2022lihan/article/details/125492487