Matrix-Tree 定理

· · 个人记录

无向生成树

为什么生成树计数会与矩阵有关?

因为树没有环 \rightarrow 树中的任意一条边都是独一无二不可或缺的 \rightarrow "线性无关"。

我们用一个矩阵表示一张图,其中每一列有且仅有两个 1-1 的位置表示两点存在一条边。

譬如 n=4 时,有一条边 (2,4) ,则可以表示为:

\begin{bmatrix} 0 \\ 1 \\ 0 \\ -1 \end{bmatrix} \text{或者} \begin{bmatrix} 0 \\ -1 \\ 0 \\ 1 \end{bmatrix}

有多条边我们把它们像图书馆藏书一样靠紧即可。

比如 n=4,m=3,边为 (1,2),(1,3),(2,3),则可以表示为:

\begin{bmatrix} 1 & -1 & 0\\ -1 & 0 & 1\\ 0 & 1 & -1\\ 0 & 0 & 0 \end{bmatrix}

这叫做关联矩阵

那么求生成树的个数,等价于有多少 n-1 条边的组合不出现环且联通。

等价于关联矩阵有多少个 n-1 列的组合线性无关。

对于我们这个关联矩阵 n-1 列的组合,它的行列式只能是 -1,0,1,其中 0 代表线性相关,这是非常好的性质。

容易发现,关联矩阵有一行是没有用的,因为我们知道了边的一端,另一端必然可以知道。

Binet-Cauchy定理

对于 n\times m 的矩阵 Am\times n 的矩阵 B,有:

\det(AB)=\sum\limits_{S\subset U,|S| = n} \det(A_S) \det(B_S) ~~至于证明,我不会~~ 令关联矩阵为 $D$,我们要计算线性无关的方案。 我们令 $A=D,B=D^{T}$ 带入上述公式。 发现 $\det(AB)=\det(DD^T)$ 正好就是线性无关的方案数,也就正好是生成树个数。 于是直接计算的复杂度是 $O(n^2m)$。 不如直接观察 $DD^T$ 代表什么东西。 $DD^T_{i,i}$,计算方法就是把 $D$ 的第 $i$ 行向量点乘自己,也就表示点 $i$ 的度数。 $DD^T_{i,j}$,手玩得 $(i,j)$ 之间边的数量的**相反数**。 于是这个矩阵(称之**基尔霍夫矩阵**)就可以直接 $O(edge)$ 得到,再花费 $O(n^3)$ 高斯消元计算行列式即可。 计算行列式就高斯消元只保留右上三角,左下全是 $0$。 $O(n^3)$ 或者 $O(n^3\log p)$(无逆元辗转相减)。 ## 各类生成树计数 ### 有向生成树 一个记忆的方法: - 指向根就不用在意根的出边,所以度数矩阵变成出度矩阵。 - 指向叶子就不用在意根的入边,所以度数矩阵变成入度矩阵。 ### 权值为边权乘积 $\prod

直接看成重边即可。

权值为边权和 \sum

需要计算每条边的出现次数乘上权值,暴力做是 O(n^3m) 的,非常不优秀。

我们用一些线性代数知识来优化复杂度。

内向生成树

首先定义一个方阵 A余子式 m_{i,j}把矩阵第 ij 列去掉后矩阵的行列式

代数余子式 M_{i,j}=m_{i,j}\times (-1)^{i+j}

于是所有的代数余子式也构成了一个矩阵 M。那么我们怎么求这个矩阵呢?

幸好我们有一个叫做拉普拉斯定理的东西:

\begin{aligned} \det(A)=\sum_{j=1}^{n}A_{i_1,j}\times M_{i_2,j} & \quad(i_1=i_2)\\ 0=\sum_{j=1}^{n}A_{i_1,j}\times M_{i_2,j} & \quad (i_1\not = i_2) \end{aligned}

定义 A伴随矩阵M^TM转置)。那么根据拉普拉斯公式显然有:

AM^T=\det(A)I

其中 I 是单位矩阵。

这也告诉了我们一种 O(n^3) 求代数余子式矩阵 M 的方法:

M=(A^{-1}\det(A))^T

回归正题,我们怎么用这个代数余子式矩阵快速求删除一条边后的矩阵行列式值呢?

由于这是个内向生成树,一条边 u\to v 的删除等价于修改了基尔霍夫矩阵 A 的:

\begin{aligned} A_{u,u} \gets A_{u,u}-1 \\ A_{u,v}\gets A_{u,v} + 1 \end{aligned}

因为它们位于同一行,我们求得了原矩阵的行列式、代数余子式后,就可以用拉普拉斯公式 O(1) 修正成删除这条边的行列式。

二者作差便是边 u \to v 在所有生成树中的出现次数了。

于是我们可以 O(n^3+m) 求的内向生成树的权值和。

外向生成树

外向生成树改变的是

\begin{aligned} A_{v,v} \gets A_{v,v}-1 \\ A_{u,v}\gets A_{u,v} + 1 \end{aligned}

改变的是同一列。据百度百科所言,拉普拉斯定理在取列而不是行的时候也是正确的。

所以跟内向生成树做法一致。

其实刚刚看《线性代数》看到了一个性质:行列式转置后值不变这从侧面印证了外向生成树是可做的。

无向生成树

如果继续使用上面的办法,则删除一条边要改动 4 个值……不过百度百科还说,我们上文说的那个拉普拉斯定理只是弱化版本,真正的拉普拉斯定理是:

n 阶行列式 D=|a_{i,j}| 中,任意取定 k 行(列)(1 \le k \le n),由这 k 行(列)的元素所构成的一切 k 阶子式与其代数余子式的乘积的和等于行列式 D 的值。

上面我们计算有向生成树的时候用到的是 k=1,现在是 k=2 的。不过好在二阶行列式跟叉积一样,很好算,所以依然是可做的。

不过万一有人问:“你这做法太数学化了!有没有什么正常 oier 就能会的做法?”我会告诉你,有的。

另一种求生成树权值和的做法

此做法通用于有向无向。

将矩阵的每一个位置用 wx+1 的形式表示。