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: 实际计算时并不需要连接删边的操作,这样的描述仅便于理解。


代码

posted @ 2022-06-27 22:14  C2022lihan  阅读(19)  评论(0编辑  收藏  举报