最小生成树的增量构造与在线最小生成树(Incremental MST)问题
题目描述
假设我们有一个无向连通图,初始时没有边。现在我们需要处理一系列在线的加边操作。每次加边后,我们需要立即得到当前图的最小生成树(Minimum Spanning Tree, MST)的总权重,并能够高效维护这个 MST 的结构。
输入:一个无向图,初始只有 n 个顶点(编号 0 到 n-1),没有边。之后依次给出 m 条边的插入操作,每条边包含三个整数 (u, v, w),表示在顶点 u 和 v 之间添加一条权重为 w 的边。
输出:每次加边操作后,输出当前图的最小生成树的权重。如果当前图还不连通,则输出 "Disconnected"。
限制:n 可以很大(例如 ≤ 10^5),m 也可能很大(≤ 2×10^5),因此需要每次加边后能快速更新 MST,而不能每次重新计算。
核心思路
这个问题实际上是一个动态图 MST 维护问题,但这里的动态只包含“加边”操作(是增量构造),不包含删边。
我们可以利用这样一个性质:如果当前图已经有了一个 MST,新加入一条边 e 后,新的 MST 的边集要么不变,要么是原 MST 的边集加上 e,然后删去原 MST 中形成的环里的最大权重边。
步骤 1:初始状态
初始时,图是 n 个孤立顶点,没有边。MST 不存在,总权重为 0,但图不连通,所以输出 "Disconnected"。
步骤 2:维护数据结构
我们需要:
- 一个能表示当前 MST 的树结构,并支持快速查询树上两点之间的最大边权重。
- 当新边加入时,判断是否加入 MST 并更新。
具体选择:
- 用并查集维护连通性(如果当前 MST 不包含所有顶点,则图不连通)。
- 用动态树(Link-Cut Tree, LCT) 来维护当前 MST 树,它能支持在 O(log n) 时间内查询树上任意两点间的最大权重边,并支持删掉最大边、加入新边。
步骤 3:增量更新 MST 的规则
设当前图是 G,当前 MST 是 T,新边是 e=(u,v,w)。
情况 1:u 和 v 在当前 T 中不连通(即整个图原本不连通,或者这两个分量在 T 中没有边连接)。
这时,加入 e 会连接两个连通分量,那么直接将 e 加入 MST 即可,不会形成环。
更新:T = T ∪ {e}。
情况 2:u 和 v 已经在 T 中连通。
那么在 T 中 u 到 v 的路径上,找到最大权重的边 e_max。
- 如果 w < weight(e_max),则 e 比 e_max 更优,用 e 替换 e_max,新的 MST 总权重减少 weight(e_max)-w。
- 如果 w ≥ weight(e_max),则 MST 不变。
步骤 4:连通性判断
即使 T 是当前 MST,它也可能没有连接所有顶点(当图还不连通时)。
我们用并查集维护实际连通性(不仅是 T 中的连通性,因为可能有非树边连接分量)。
每次加边 (u,v,w),先用并查集检查 u 和 v 是否连通,以此判断是否连接了两个不同连通分量。
- 如果不连通,加入 e 后,图可能还是不一定全连通,但至少 u 和 v 所在的分量合二为一。
此时直接将 e 加入 T,并更新并查集。 - 如果连通,走情况 2 的判断替换步骤。
步骤 5:算法流程
初始化:
parent[n] 为并查集
T 为空(用 LCT 表示)
total_weight = 0
components = n // 当前连通分量个数
对每条新边 e = (u, v, w):
如果 components > 1:
如果 find(u) != find(v):
将 e 插入 LCT 的 T 中
union(u, v)
total_weight += w
components -= 1
否则:
// u, v 已连通
在 T 中查询 u-v 路径上的最大边 e_max
如果 w < weight(e_max):
从 T 中删掉 e_max
在 T 中加入 e
total_weight += w - weight(e_max)
否则(components == 1,图已连通):
在 T 中查询 u-v 路径上的最大边 e_max
如果 w < weight(e_max):
从 T 中删掉 e_max
在 T 中加入 e
total_weight += w - weight(e_max)
如果 components == 1:
输出 total_weight
否则:
输出 "Disconnected"
步骤 6:LCT 如何维护最大边
LCT 的每个节点代表一条边(也可以将边转化为点,常用技巧:将边看作一个新节点连接 u 和 v)。
每个节点维护子树中最大权重边的信息。
支持操作:
link(x, y):连接两个节点cut(x, y):断开边query_max(u, v):查询 u-v 路径上的最大权重边
实现时,将边 (u,v,w) 表示为一个新节点 p,权重为 w,然后连接 p-u 和 p-v。
步骤 7:复杂度分析
- 每次操作:O(log n)(LCT 操作时间)。
- 总体 O((n+m) log n)。
- 可以处理 n,m 达到 10^5 数量级。
步骤 8:简单例子
n=3,初始 3 个孤立点,components=3,total=0,T 为空。
-
加边 (0,1,4):
0 和 1 不连通 → 加入 T,total=4,components=2,输出 "Disconnected"。 -
加边 (1,2,3):
1 和 2 不连通 → 加入 T,total=7,components=1,输出 7。 -
加边 (0,2,5):
已连通,原 MST 中 0-2 路径是 0-1(4) 和 1-2(3),最大权重边是 4。
5>4,不替换,total=7,输出 7。 -
加边 (0,2,2):
已连通,原路径上最大权重边是 4,2<4,替换 4 的边,
total = 7 - 4 + 2 = 5,输出 5。
小结
这个算法是在线 MST 维护的经典方法,利用“环中最大边替换”的性质,借助动态树快速更新。它只适用于加边操作,对于删边则需要更复杂的数据结构(动态 MST 完全体)。