最小生成树的 Kirchhoff 定理
题目描述
给定一个无向带权连通图 \(G = (V, E)\),其中每条边有一个正整数权重,我们要求出该图的所有不同最小生成树(Minimum Spanning Tree, MST)的数量。注意,如果两条生成树的边集不完全相同,即使它们的总权重相等,也被视为不同的生成树。这个问题要求我们计算图中权值和最小的生成树的总个数,通常称为“最小生成树计数”问题。我们将利用 Kirchhoff 定理(也称为矩阵树定理)来解决它。
解题过程
步骤1:理解问题核心
在最小生成树计数中,我们不仅要找出一个 MST,还要统计所有权值和等于最小权值和的所有生成树的数量。直接枚举所有生成树并比较权值是不可行的,因为生成树的数量可能是指数级的。Kirchhoff 定理是解决无向图所有生成树计数问题的经典方法,但这里我们只关心权值和最小的那些生成树。因此,我们需要将 Kirchhoff 定理与最小生成树的性质结合起来。
步骤2:回顾 Kirchhoff 定理
Kirchhoff 定理指出:对于一个无向图 \(G\),其生成树的数量等于其拉普拉斯矩阵(Laplacian Matrix)的任意一个余子式的绝对值。具体地:
- 构建图的度矩阵 \(D\):这是一个 \(|V| \times |V|\) 的对角矩阵,其中 \(D_{ii}\) 等于顶点 \(i\) 的度数,非对角元素为 0。
- 构建图的邻接矩阵 \(A\):其中 \(A_{ij} = 1\) 如果顶点 \(i\) 和 \(j\) 之间有边,否则为 0(对于无向图,\(A\) 是对称的)。
- 拉普拉斯矩阵 \(L = D - A\)。
- 去掉 \(L\) 的任意一行和一列(例如去掉第 \(k\) 行和第 \(k\) 列),得到一个 \((|V|-1) \times (|V|-1)\) 的子矩阵 \(L'\)。
- 生成树的数量 = \(|\det(L')|\)。
但这是针对无权图(或等价地,所有边权重视为 1)的情况。对于带权图,如果每条边的权重为 \(w_e\),我们可以将 Kirchhoff 定理推广为:生成树的总权重和(即所有生成树的边权重乘积之和)等于加权拉普拉斯矩阵的余子式。然而,我们这里只关心最小生成树计数,而不是所有权重乘积之和。
步骤3:最小生成树的关键性质
我们需要利用最小生成树的一个重要性质:在无向带权连通图中,所有权重相同的边在最小生成树计数问题中具有等价性。更具体地,考虑图中所有边的权重,最小生成树的权值和记为 \(W_{\text{min}}\)。对于任意权重值 \(w\),所有权重为 \(w\) 的边在最小生成树中的出现情况可以由以下步骤确定:
- 运行 Kruskal 算法(或 Prim 算法)找出一个最小生成树,并记录下最小权值和 \(W_{\text{min}}\)。
- 在 Kruskal 算法过程中,当处理某一特定权重的边时,这些边可能会形成多个连通分量,而选择哪些边加入 MST 会影响生成树的数量。
步骤4:将问题转化为多个子问题
最小生成树计数的一个标准方法是:
- 将图中的边按权重从小到大排序,相同权重的边分为一组。
- 初始化一个并查集(Union-Find),维护当前已加入的边形成的连通分量。
- 按权重递增顺序处理每一组相同权重的边:
a. 将当前组中的所有边涉及的顶点,映射到它们所在的连通分量(即缩点后的新顶点)。
b. 对每个连通分量,构建一个子图,其中顶点是该连通分量内的原始顶点,边是当前组中连接该连通分量内顶点的边(注意,这些边在当前组处理前不会连接不同的连通分量,否则会形成环,但可能连接同一分量内的顶点)。
c. 对于每个这样的子图,计算其所有生成森林(即保持连通性不形成环的边选择方式)的数量。但更精确地说,我们需要计算在当前连通分量内,选择当前组中的边使得分量保持连通(即不形成环)的方案数。实际上,这等价于在该连通分量对应的图中,计算所有生成树的数量(因为当前组边加入后,不能形成环,且必须连接分量内的所有顶点)。
d. 利用 Kirchhoff 定理计算每个子图的生成树数量,然后将所有子图的生成树数量相乘,得到当前组边对总方案数的贡献。
e. 将当前组中必须加入的边(即在 Kruskal 算法中会加入的边)实际合并到并查集中,更新连通分量。
步骤5:Kirchhoff 定理的具体应用
对于每个子图(对应一个连通分量),我们构建其加权拉普拉斯矩阵,但这里边权重都是相同的(因为属于同一权重组),所以我们可以暂时将权重视为 1,即使用无权图的 Kirchhoff 定理。这是因为所有权重相同,任何生成树的边数相同,权重乘积也相同,因此生成树的数量与权重无关。具体步骤:
- 设子图有 \(n\) 个顶点(即该连通分量中的顶点数),\(m\) 条边(即当前组中连接这些顶点的边)。
- 构建子图的拉普拉斯矩阵 \(L\):度矩阵 \(D\) 中 \(D_{ii}\) 是顶点 \(i\) 在子图中的度数,邻接矩阵 \(A\) 中如果顶点 \(i\) 和 \(j\) 之间有边则 \(A_{ij} = 1\)。
- 计算 \(L\) 的任意一个余子式(例如去掉第一行和第一列)的行列式绝对值,即为该子图的生成树数量。
步骤6:算法步骤总结
- 输入:无向带权连通图 \(G = (V, E)\),边权重为 \(w(e)\)。
- 将边按权重 \(w(e)\) 非递减排序,相同权重的边分组。
- 初始化并查集 UF,每个顶点单独一个集合。初始化答案 \(\text{ans} = 1\)。
- 遍历每个权重组(按权重从小到大):
a. 对于当前组中的所有边,找出这些边涉及的所有顶点,并确定每个顶点在 UF 中的根(即所属连通分量)。
b. 将属于同一连通分量的顶点聚合,每个连通分量形成一个子图。注意,不同连通分量之间的边(即连接两个不同分量的边)在当前组中可能出现,但这些边是必须加入的(否则无法形成 MST),我们稍后处理。
c. 对于每个连通分量对应的子图:- 构建该子图的顶点集合(原始顶点),边集是当前组中连接该子图内顶点的边。
- 如果子图的边数 \(m\) 大于等于顶点数 \(n\),则可能形成环,我们需要计算该子图的生成树数量。如果 \(m < n-1\),则生成树数量为 0(实际上这种情况不会发生,因为 MST 要求连通),但根据算法,此时子图不连通,实际上当前组中必须有一些边连接不同分量,所以子图可能不连通。我们需要计算的是:在当前连通分量内,选择当前组中的边使得该分量保持连通(即不形成环)的方案数。准确地说,我们应该计算该子图的“最大生成森林”中树的数量,但更简单的做法是:将当前组中连接该分量内顶点的边全部考虑,然后计算这些边形成的图中,包含所有顶点的生成树数量。如果子图不连通,则生成树数量为 0,但这种情况意味着无法形成 MST,所以整个图的 MST 数量为 0。在最小生成树计数中,通常假设图是连通的,且每组边处理时子图是连通的。
- 使用 Kirchhoff 定理计算生成树数量 \(t\)。
- 将 \(\text{ans}\) 乘以 \(t\)。
d. 将当前组中所有边尝试加入并查集:对于每条边 \((u, v)\),如果 \(u\) 和 \(v\) 不在同一连通分量,则合并它们(这对应于 Kruskal 算法中必须加入的边)。注意,如果 \(u\) 和 \(v\) 在同一分量,则这条边不能加入(会形成环),但我们已经在子图生成树计数中考虑了不选它的可能性。
- 返回 \(\text{ans}\)。
步骤7:复杂度分析
- 排序边:\(O(|E| \log |E|)\)。
- 并查集操作:近似 \(O(|E| \alpha(|V|))\)。
- 对于每个权重组,我们需要对每个子图应用 Kirchhoff 定理,这需要计算一个 \(n \times n\) 矩阵的行列式,复杂度为 \(O(n^3)\)。最坏情况下,所有子图的大小之和可能达到 \(O(|V|)\),但每个边组只处理一次,总复杂度取决于子图的大小分布。实践中,如果图是稀疏的,这个算法是可行的。
步骤8:示例
考虑一个简单的图:三个顶点 \(A, B, C\),边 \((A,B)\) 权重 1,\((B,C)\) 权重 1,\((A,C)\) 权重 2 \)。
- 排序边:权重 1 的边为一组:\((A,B), (B,C)\);权重 2 的边为一组:\((A,C)\)。
- 处理第一组(权重 1):
- 初始并查集:每个顶点独立。
- 当前组边涉及顶点 A,B,C,它们属于不同分量,所以子图包含三个顶点,两条边。但注意,这两条边连接不同分量,实际上它们都是必须加入的(因为不加入就无法连通),但根据算法,我们先计算子图生成树数量:子图有 3 个顶点,2 条边,其生成树数量为 2(因为生成树需要 2 条边,但这里只有 2 条边,且它们形成一条路径,所以生成树数量为 1?等会儿,我们重新检查:子图顶点集 {A,B,C},边集 {(A,B), (B,C)},这个子图本身是一棵树,所以生成树数量为 1。实际上,Kirchhoff 定理计算:拉普拉斯矩阵 L = [[1,-1,0],[-1,2,-1],[0,-1,1]],去掉第一行第一列得到 [[2,-1],[-1,1]],行列式为 21 - (-1)(-1) = 1,所以生成树数量为 1。
- ans = 1 * 1 = 1。
- 将边 (A,B) 和 (B,C) 加入并查集,现在三个顶点在同一连通分量。
- 处理第二组(权重 2):
- 当前组边 (A,C) 涉及顶点 A 和 C,它们在同一个连通分量,所以子图包含顶点 A 和 C,但边 (A,C) 连接它们,子图有两个顶点一条边。计算生成树数量:2 个顶点的树只有一条边,所以生成树数量为 1。
- ans = 1 * 1 = 1。
- 边 (A,C) 不加入(因为会形成环)。
- 最终最小生成树数量为 1。实际上,这个图只有一棵最小生成树(总权重 2)。
总结
通过结合 Kruskal 算法的边分组处理与 Kirchhoff 定理,我们可以高效计算无向带权连通图中最小生成树的数量。关键是将相同权重的边分组,对每个组在当前的连通分量上构建子图,并利用 Kirchhoff 定理计算子图的生成树数量,最后将各组数量相乘得到总数。