康复计划#5 Matrix-Tree定理(生成树计数)的另类证明和简单拓展

  本篇口胡写给我自己这样的什么都乱证一通的口胡选手 以及那些刚学Matrix-Tree,大致理解了常见的证明但还想看看有什么简单拓展的人…

  大概讲一下我自己对Matrix-Tree定理的一些理解、常见版本的证明、我自己的证明,以及简单的一些应用(比如推广到有向图、推广到生成树边权的乘积和什么的,非常基础)。

  应该看到这里的人都知道Matrix-Tree定理是干什么的吧…就是统计一个无向图的生成树个数,表示成一个行列式。

1、前置定义及性质

  首先是Matrix-Tree定理相关的定义:对于一个无向图 $ G=(V,E) $,记 $ |V|=n,|E|=m $,

  定义它的度数矩阵为 $ D_G $,对于所有 $ 1 \leq i \leq n $,第 $ i $ 行 $ i $ 列的项 $ d_{ii} $ 为点 $ i $ 的度数,其余项为 $ 0 $ ;

  定义它的邻接矩阵为 $ A_G $,对于所有 $ 1 \leq i,j \leq n $,第 $ i $ 行第 $ j $ 列的项 $ a_{ij}= $ 点 $ i $ 到 $ j $ 的连边数(可以有重边)。

  定义它的基尔霍夫矩阵为 $ L_G=D_G-A_G $,即主对角线上是每个点的度数,其它地方 $ l_{ij}=-a_{ij}, i \neq j $ 。基尔霍夫矩阵的性质放在下一节进行讨论。

  另外还有一个边矩阵 $ B_{m \times n} $,每行有两个非零元素,对于第 $ i $ 条边 $ (s_i,t_i) $, $ b_{is_i}=1, b_{it_1}=-1 $ 。根据定义容易证明 $ L_G=B^T B $ (列出式子就是显然的了)。这个矩阵在常见的证明方法里会用到。

  然后说一下需要用到的几个行列式的基本性质。

  1、拉普拉斯展开

  对于行列式

   $$ D = \begin{vmatrix}a_{11} & a_{12} & \cdots & a_{1n} \\ a_{21} & a_{22} & \cdots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{n1} & a_{n2} & \cdots & a_{nn}\end{vmatrix} $$

  对任意的第 $ i $ 行 $ (1 \leq i \leq n) $,按下式展开,值均等于原行列式的值。

   $$ D = \sum_{j=1}^{n} (-1)^{i+j} a_{ij} M_{ij} $$

  其中 $ M_{ij} $ 称作 $ a_{ij} $ 的余子式,代表行列式 $ D $ 去掉第 $ i $ 行和第 $ j $ 列的全部元素,剩下的行和列按原顺序排列的 $ n-1 $ 阶行列式。

  通过归纳法可以证明。

  2、行列式线性性

  (1)

   $$ \begin{vmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ \vdots & \vdots &  & \vdots \\ ka_{i1} & ka_{i2} & \cdots & ka_{in} \\ \vdots & \vdots &  & \vdots \\ a_{n1} & a_{n2} & \cdots & a_{nn} \end{vmatrix} = k \begin{vmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ \vdots & \vdots &  & \vdots \\ a_{i1} & a_{i2} & \cdots & a_{in} \\ \vdots & \vdots &  & \vdots \\ a_{n1} & a_{n2} & \cdots & a_{nn} \end{vmatrix}  $$

  (2)

   $$ \begin{vmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ \vdots & \vdots &  & \vdots \\ a_{i1}+b_{i1} & a_{i2}+b_{i2} & \cdots & a_{in}+b_{in} \\ \vdots & \vdots &  & \vdots \\ a_{n1} & a_{n2} & \cdots & a_{nn} \end{vmatrix} = \begin{vmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ \vdots & \vdots &  & \vdots \\ a_{i1} & a_{i2} & \cdots & a_{in} \\ \vdots & \vdots &  & \vdots \\ a_{n1} & a_{n2} & \cdots & a_{nn} \end{vmatrix} + \begin{vmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ \vdots & \vdots &  & \vdots \\ b_{i1} & b_{i2} & \cdots & b_{in} \\ \vdots & \vdots &  & \vdots \\ a_{n1} & a_{n2} & \cdots & a_{nn} \end{vmatrix}  $$

  这两个性质按第 $ i $ 行展开就可以立刻得到。

  3、做倍加行变换,行列式值不变

   $$ \begin{vmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ \vdots & \vdots &  & \vdots \\ a_{i1} & a_{i2} & \cdots & a_{in} \\ \vdots & \vdots &  & \vdots \\ a_{n1} & a_{n2} & \cdots & a_{nn} \end{vmatrix} = \begin{vmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ \vdots & \vdots &  & \vdots \\ a_{i1}+ka_{j1} & a_{i2}+ka_{j2} & \cdots & a_{in}+ka_{jn} \\ \vdots & \vdots &  & \vdots \\ a_{n1} & a_{n2} & \cdots & a_{nn} \end{vmatrix}  $$

  可以通过归纳法证明一个性质:如果有两行元素对应相等,则行列式值为 $ 0 $ 。有了这个性质再通过线性性即可证明。

  4、两行对换,行列式反号

  通过线性性和倍加行变换即可证明。(对于 $ i,j $ 两行对换,把第 $ j $ 行加到第 $ i $ 行上,再从第 $ j $ 行减去现在的第 $ i $ 行,然后在第 $ j $ 行提出 $ -1 $ 即可)

  5、上/下三角行列式的值等于主对角线元素乘积。

  直接展开即可得到。

2、Matrix-Tree定理及证明

  Matrix-Tree定理

    对于无向图 $ G=(V,E) $,图的生成树个数等于任何一个 $ n-1 $ 阶主余子式 $ M_{ii} $ (删掉的行列编号相同的余子式)的值。

  利用这个定理,结合高斯消元求行列式(把行列式消成上三角,消元过程中行列式的值的变化由上面的性质可以算出)可以做到 $ O(n^3) $ 求出一个无向图的生成树个数。

  下面我们讨论它的证明。

2.1、常见证明方法(简略版)

  由于我没有找很多资料,不知道有没有用我这种方法的正式证明…所以我的证明的严谨性可能不会有完全的保障…所以为了防止坑到萌新,在给出我的证明方法之前还是简略地讲一下常见的证明方法吧

  首先我们注意到基尔霍夫矩阵有一些性质,它的每行元素和都是 $ 0 $,每列元素和也是 $ 0 $,所以如果我们把所有行都加到其中一行,这一行就会变成全 $ 0 $,于是如果我们按这一行展开就能得到 $ L_G = 0 $ 。

  有了这个性质,我们可以证明如果 $ G $ 不连通,那么任意 $ M_{ii}=0, 1 \leq i \leq n $ 。因为如果 $ G $ 不连通, $ L_G $ 就可以通过若干次行对换和列对换(每次交换 $ i,j $ 两行,然后交换 $ i,j $ 两列,那么行列式的值经过两次反号是不变的)把通一个连通块的编号排在一起,那么 $ L_G $ 会变成:

   $$ L_G = \begin{vmatrix}A_1 & &  & \\ & A_2 &  & \\ & & \ddots & \\ & & & A_k \end{vmatrix} $$

  其中 $ k $ 为连通块个数, $ A_i $ 是一些矩阵,大小为对应连通块大小。这是把原行列式给分块了,其余位置全是 $ 0 $ 。这种对角块矩阵具有一个性质,就是它的行列式等于所有 $ A_i $ 的行列式的乘积。证明也很简单,只要通过高斯消元把 $ A_i $ 全部消成上三角,那么整个 $ L_G $ 也会是上三角的,所以 $ |L_G| $ 就等于 $ |A_i| $ 的乘积(它们在消元过程中产生的变化是相同的)。

  如果 $ G $ 不连通,那么 $ k \geq 2 $,于是考虑 $ L_G $ 的主余子式 $ M_{ii} $,它仍然是一个对角块矩阵,并且至少包含了一个完整的 $ L_G $ 中的 $ A_x $ 。而因为 $ A_x $ 是一个连通块的信息,它就是 $ G $ 的一个完整的导出子图的基尔霍夫矩阵,所以完整的 $ A_x $ 的行列式 $ |A_x|=0 $ 。于是整个 $ |M_{ii}|=0 $ 。

  接下来还有一个性质,若 $ G $ 是树,则 $ M_{ii}=0 $ 。这个可以通过归纳法证明,这里略过,在下一部分我会给出我的证明。

  然后我们需要用到一个定理:Cauchy-Binet定理。对于一般矩阵 $ A,B $ (不一定是方阵)

   $$ |AB| = \sum_{|s|=n} |A_{s*}B_{*s}| $$

  其中 $ s $ 是集合 $ {1,2,\cdots,m} $ 的一个大小为 $ n $ 的子集, $ A_{s*} $ 表示 $ A $ 只取 $ s $ 中的列形成的 $ n \times n $ 方阵。

  因为本文重点不在这里,所以就不加证明地给出这个定理(才不是我怕写太长或者我很懒)。

  于是通过这个定理我们可以得到

   $$ M_{ii} = |B_i^TB_i| = \sum_{|s|=n-1} |(B_i^T)_{s*}(B_i)_{*s}| $$

  其中 $ B_i $ 代表 $ B $ 删去第 $ i $ 列后得到的 $ m \times (n-1) $ 矩阵。注意到右侧就是只取 $ n-1 $ 条边时的 $ B_i $ 的乘积,也就是 $ G $ 中只留下 $ s $ 中的边时得到的 $ M_{ii} $,根据上面得到的两个小性质,我们知道在刚好构成树时它是 $ 1 $,否则一定不连通,所以是 $ 0 $ 。于是这就证明了Matrix-Tree定理。

2.2、我口胡的另外一个证明方法(正题)

  [注] 如果有人发现我的证明有什么地方出现了错误,请务必留言怼我

  前段时间我看到了一道看起来能用Matrix-Tree的推广的题目,于是愉快地写了一下,但是写完之后发现我已经忘了Matrix-Tree定理怎么证明,更不用说怎么推广了…于是我冥思苦想了几个小时,突然发现了一些有趣的东西,这引出了对于Matrix-Tree定理的另一个理解。

  我最初是为了证明上面提到的一个性质“若 $ G $ 是树,那么 $ M_{ii}=1 $ ”想的这个办法。我试图使用归纳法…(但是失败了…引向了另外的方向)

  考虑把 $ L_G $ 删去第一行和第一列,那么我们得到的行列式其实类似于把 $ 1 $ 号点删去后得到的图 $ L_{G‘} $ 的基尔霍夫矩阵,但是其中有若干个点的度数并不是在 $ G‘ $ 中的度数,因为我们删去一行一列时并没有调整它们。于是实际上得到的是:

   $$ \begin{vmatrix}d‘_2 + \Delta_2 & -a_{23} & \cdots & -a_{2n} \\ -a_{32} & d‘_3 + \Delta_3 & \cdots & -a_{3n} \\ \vdots & \vdots & \ddots & \vdots \\ -a_{n2} & -a_{n3} & \cdots & d‘_n + \Delta_n \end{vmatrix} $$

  其中 $ a_{ij} $ 是邻接矩阵 $ A_G $ 中的元素; $ d‘_i $ 是图 $ G‘ $ 的度数矩阵 $ D_{G‘} $ 中的元素; $ \Delta_i $ 等于 $ 1 $ 号点与 $ i $ 号点连边数。

  因为这太相似了,所以考虑使用行列式线性性质的第(2)条把它们拆开。比如我们拆开 $ d‘_3 $ 和 $ \Delta_3 $ :

   $$ \begin{vmatrix}d‘_2 + \Delta_2 & -a_{23} & \cdots & -a_{2n} \\ -a_{32} & d‘_3 + \Delta_3 & \cdots & -a_{3n} \\ \vdots & \vdots & \ddots & \vdots \\ -a_{n2} & -a_{n3} & \cdots & d‘_n + \Delta_n \end{vmatrix} = \begin{vmatrix}d‘_2 + \Delta_2 & -a_{23} & \cdots & -a_{2n} \\ -a_{32} & d‘_3 & \cdots & -a_{3n} \\ \vdots & \vdots & \ddots & \vdots \\ -a_{n2} & -a_{n3} & \cdots & d‘_n + \Delta_n \end{vmatrix}+\begin{vmatrix}d‘_2 + \Delta_2 & -a_{23} & \cdots & -a_{2n} \\ 0 & \Delta_3 & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ -a_{n2} & -a_{n3} & \cdots & d‘_n + \Delta_n \end{vmatrix}  $$

  右边的两个还可以继续拆开别的 $ d‘_i+\Delta_i $ 。我们每拆开一项,就会让行列式数量乘以 $ 2 $ 。如果剩下的图中与 $ 1 $ 号点相连的点集是 $ S $,大小为 $ k $,那么就有 $ k $ 个非零的 $ \Delta_i $,我们将得到 $ 2^k $ 个行列式。

  我们断言,这 $ 2^k $ 个行列式里面至多只有 $ 1 $ 个非零。而且这个非零的行列式就是每次展开到右边的那个在 $ k $ 行中只含 $ \Delta_i $ 的行列式。

  这是因为原图是一棵树,所以去掉 $ 1 $ 号点后的每个连通块都恰好有一个点 $ i $ 对应的 $ \Delta_i $ 是 $ 1 $ 。注意到拆出来在左边的那个行列式在 $ i $ 所在的连通块内的项都是正确的 $ L_{G‘} $ 中的项,于是还是按照上面的方法把现在的行列式转化为对角块矩阵,然后现在对角线上出现了一个基尔霍夫矩阵,于是不管剩下的对角块上是什么,行列式的值都是 $ 0 $ 。那么有可能非零的行列式就只剩下最右边那个了。

  接下来,我们对最右边的那个行列式的带非零 $ \Delta $ 的 $ k $ 行都做一次按行展开,因为这 $ k $ 行里每行都只有 $ \Delta_i $ 这个位置非零,所以得到的也只有一项,这一项就是它删掉这 $ k $ 行和 $ k $ 列的元素后的行列式,乘以所有 $ k $ 个 $ \Delta_i, i \in S $ 的乘积(这里就是 $ 1 $ )。我们看看这个行列式是什么样子,除了我们删去了一些行和对应列之外,剩下的部分没有改动,这和我们最初的情况很类似,实际上这差不多是删去 $ \{ 1 \} \cup S$ 中的点后得到的图 $ G‘‘ $ 的基尔霍夫矩阵,只是其中有些点的度数大于实际在 $ G‘‘ $ 中的度数。实际上这些增加的量只会是 $ 0 $ 和 $ 1 $,因为这相当于现在我们取走的点集中与每个点相邻的点数,而我们已经取走的点集是树上连续的一块,因为整张图是一棵树,所以剩下的每个点至多之和已经取走的点集有一条连边。于是我们得到了和上面形式一致的结果,这意味着我们可以再做一次。

  最后会变成什么样呢?其实如果我们一直这么做下去的话会得到 $ 1 $ 乘以一个空的行列式(但是这其实是不行的,只有一阶的时候我们无法继续展开),所以回到上一步,那就是 $ 1 $ 乘以一阶行列式 $ |1| $,那么结果就是 $ 1 $ 。(然后我们就可以用常见方法证明辣)

  这个过程看起来有点投机取巧的味道…确实…因为我本来是知道结论的…

  不过这个过程中我受到了一些启发,让我觉得这种方法说不定可以推广到一般无向图。

  首先我们回顾我们在树上的过程:我们选取了一个点删去,然后找到所有与它相连的点并删去,然后再找到所有与已经选的点集相连的点并删去…最后所有点都被删去了。这仿佛就是一个BFS的过程…实际上这确实就是一个BFS的过程,我们一次直接扩展了一层节点。

  为了推广到一般无向图,我们需要继续考虑一下这个过程(因为树从一个点出发的BFS过程是唯一的,但是一般无向图有许多生成树,对应了不同的BFS过程)。我们其中有一步得到了 $ 2^k $ 个行列式,是的,我们证明其中 $ 2^k-1 $ 个都是 $ 0 $ 之后就不管了。而在一般无向图上并不是这样,因为只要剩下的图中每个连通块至少一个点被展开成 $ \Delta $ 就可以了(只是为了避免出现某个连通块是完整的基尔霍夫矩阵)。这一点又启发我们发现展开这一步隐含的意义。

  先在树上考虑一下:这仿佛是枚举了已选点集和剩下点集之间的 $ k $ 条边是否在生成树中,因为是一棵树,所以如果有一条边不在就会独立出一个连通块,不合法。

  看起来很有道理,但是在一般无向图上没有道理。因为 $ k $ 是这一层的点集大小,对于一般无向图来说,并不是每个点都只有唯一的前驱边(可能上一层多个点都能和这个点有边,而且一般无向图可能有重边),所以 $ k $ 代表的不是边数。实际上它的意义只是枚举了下一次要扩展的点集而已,但是可能还会有奇怪的感觉,因为一般无向图上单靠每层的点集是无法确定生成树的(原因还是刚刚那一句话)。我们现在重新考察一下 $ \Delta $ 来打消这个顾虑。

   $ \Delta_i $ 等于上一层已取点集中与 $ i $ 相邻的点数。假如现在我们新扩展了一层,点集为 $ S $,那么原本BFS树上的每种情况实际上都对应 $ \prod_{i \in S} \Delta_i $ 种情况。因为确定点集后每个点 $ i $ 选择它的前驱边就是 $ \Delta_i $ 种选法。当我们按 $ \Delta_i $ 所在那一行展开的时候它正好被我们提了出来,所以计数仍然是正确的。这里需要解释一下为什么是上一层点集而不是已取的所有点,如果在上一层之前的某层就和点 $ i $ 在原图上有边,而点 $ i $ 当时并没有加入,那么点 $ i $ 在剩下的行列式中的度数会变成它在剩下的图中的实际度数(注意我们开始的展开就是分裂成“保留该点且度数为实际度数”以及“乘以 $ \Delta $ 并去掉该点”的两个行列式),所以产生的 $ \Delta $ 实际上只与上一层有关(在树的证明中因为树的性质,直接用所有已取点是没问题的,但是我们推广到一般图就必须更加准确地了解情况了)。

  我们有了大致思路之后,要来确认结论在一般无向图上成立,我们大概要从几个方面入手:统计的方案合法、方案不重复、方案不遗漏。

  首先我们考察合法性:如果我们某一步枚举的扩展点集中其中一个连通块没有一个点被选,那么就无法BFS全图,对应着一系列不合法的方案,而这个时候主对角线上存在一个完整的基尔霍夫矩阵,行列式值为 $ 0 $ 。并且,根据我们的统计方法,除起点外,我们只保留BFS树上每个点与前驱的一条边,且前驱在上一层,所以不可能出现环。所以我们统计到的方案一定是生成树。

  然后考虑不重复和不遗漏:对于每棵生成树,定根为起点,那么它的形态与从起点开始的BFS树的形态是完全一致的(可以定义为 $ \forall u,v \in V, (u,v)_x \in E_{ST} \Leftrightarrow (u,v)_x \in E_{BFS} $,其中 $ E_{ST} $ 是生成树的边集, $ E_{BFS} $ 是BFS树的边集, $ (u,v)_x $ 代表的是 $ u,v $ 间的第 $ x $ 条边,因为原图可以有重边)。那么通过“形态完全一致”可以定义一个BFS树与生成树之间的一一映射,所以统计所有BFS树就等价于统计所有生成树。然后,我们在每一步通过 $ 2^k $ 枚举了所有可能的下一层点集,并且通过 $ \prod_{i \in S} \Delta_i $ 算出了相邻两层间的连边方案,根据简单的计数原理,我们可以确定我们不重不漏地统计了所有BFS树。

  于是Matrix-Tree定理在一般无向图上成立。

  这就是我对Matrix-Tree的证明方法啦(实际上也不算正式的证明…但是整理一下可以写成正式的证明…不过我想等更加确定它的正确性以后再说)。

3、简单的拓展

  Matrix-Tree从定理角度的拓展其实不是很多…无非是推广到统计别的东西,或者推广到有向图。

3.1.1、推广到统计边权乘积的和

  其实有一个简单暴力的推广办法,因为我们上面的证明支持有重边的图,所以如果边权是整数,我们直接在两个点之间连上边权那么多条边,得到的生成树个数就是所有生成树的边权乘积的和了。如果不是整数,是有理数的话,我们考虑所有边权的最简分母的一个公倍数 $ t $,我们把每条边的边权乘以 $ t $,然后统计的结果除以 $ t^{n-1} $ 就能得到我们要的结果了,考虑利用行列式线性性质(1)把 $ t^{n-1} $ 分进行列式里,刚好可以让基尔霍夫矩阵的任意一个主余子式的每一行的所有元素除以 $ t $,所以这等价于我们一开始就把基尔霍夫矩阵的每一个元素除以 $ t $ 。这样我们得到了一个推广的基尔霍夫矩阵,里面连边数量改成了边权和,度数改成了这个点连出去的边的边权和,并且Matrix-Tree定理在所有元素都是有理数的情况下成立。对于计算机上的浮点数来说这就够了,因为它们都是有理数。

  不过上面这个只是一个小技巧而已,实际上也可以正常地推广,只要考察上面的证明中有什么地方不一样了,再验证它们是否能够保持成立即可(有时我们还会进一步修改证明过程中的定义,就像从树的证明推广到一般无向图一样)。实际上边权乘积刚好符合了我们的过程(因为我们用的就是 $ \prod $ ),而边权和就不行了。如果要正经地证明推广的话只是多说一些废话,并没有什么有价值的思想,这里就不啰嗦了。

3.1.2、推广到有向图

  到有向图上可能定理就有点变样了,但大致还是在的…首先邻接矩阵改成只记出边,度数矩阵改成了只记入度,然后现在得到的基尔霍夫矩阵的主余子式 $ M_{ii} $ 代表了以 $ i $ 为根的有向生成树个数。

  这下基尔霍夫矩阵的变化比较明显,它不是对称的了,并且它的每行元素的和也不再一定是 $ 0 $ 了(现在是一个点的入度减去出边数)。但是好在每一列的和还是 $ 0 $,所以最重要的性质还没有改变,仍然可以全部行加到一行上来证明它的行列式为 $ 0 $ 。而不连通的图的基尔霍夫矩阵的主余子式的值为 $ 0 $ 这一条出现了改变,变成如果从 $ i $ 点出发不能到达所有点,则 $ M_{ii}=0 $,证明还是类似的,取不能到达的点排在一起,在主对角线上形成一块基尔霍夫矩阵。接下来删点的时候,出现 $ \Delta $ 的就是这一层点集的出边影响到的点。计数的时候原理没有变化,仍然是成立的。大致就是这样推广到有向图上。

  另外这和上一个推广没有什么冲突的地方,两个推广结合在一起也是可以的。

3.2、例子

  有了定理上的推广,用法上就有更多的变化了。这里稍微举两个小例题看看。

3.2.1、[SDOI2014]重建

  给定一个图,每条边有一个出现概率 $ p_i $,问得到原图的一个生成树的概率。数据范围是 $ n \leq 50 $ 。

  如果考虑最暴力的做法,枚举子集然后DP的话,可以通过预处理每个子集与外界恰好只有一条边的概率做到 $ O(3^n+n^22^n) $ 的复杂度。但是这个复杂度太高,一秒只能处理大约 $ 16 $ 上下的 $ n $ 。

  其实我们可以通过Matrix-Tree定理来做,因为我们写出答案的求和式就能知道是对“所有树边出现概率的乘积乘以所有非树边不出现的概率的乘积”求和,我们在这个式子里直接除以所有边不出现的概率的乘积,那么要求和的就变成“所有树边的出现概率除以它的不出现概率的乘积”了。我们把这个作为边权,用一次推广的Matrix-Tree定理就可以了。用这种方法的话算 $ 500 $ 左右的 $ n $ 都没有问题。另外这题还有一些细节,和我们的主题无关,就不讨论了。

3.2.2、毕老爷在冬令营上举的其中一个例子

  给定一个图,图上每条边是红色或蓝色,求恰有 $ k $ 条红边的生成树个数。 $ n \leq 50 $ 。

  这个就是没什么悬念的Matrix-Tree定理了,对于限制条件可以利用多项式,把红边边权设为 $ x $,蓝边为 $ 1 $ 。那么最后求行列式得到的多项式中 $ x^k $ 的系数就是答案了。同样这也是利用了边权乘积的那个推广。至于多项式情况下不方便高斯消元的问题,通过代入具体的数插值求多项式就可以解决问题。

4、总结

  所以Matrix-Tree是一个挺妙的东西…从我的这种证明方法来看,Matrix-Tree实际上是把纯粹的指数级暴力搜索过程集中在了行列式之中,而行列式凭借着数学上的基础存在比较快速的计算方法,从而很好地解决了计算上的困难。类似的思想还有Lindstr?m–Gessel–Viennot_lemma引理,它除了巧妙地进行了不合法情况的消除以外,还利用了它的式子与行列式定义的一致性,把阶乘级的复杂度降到了多项式级,同样是很聪明的解决办法。

  (最后再提醒一次…如果看到有哪里不对,记得留言怼我QwQ)

时间: 02-28

康复计划#5 Matrix-Tree定理(生成树计数)的另类证明和简单拓展的相关文章

@算法 - [email protected] matrix - tree 定理(矩阵树定理)

目录 @0 - 参考资料@ @0.5 - 你所需要了解的线性代数知识@ @1 - 定理主体@ @证明 part - [email protected] @证明 part - [email protected] @证明 part - [email protected] @证明 part - 4@ @2 - 一些简单的推广@ @3 - 例题与应用@ @0 - 参考资料@ MoebiusMeow 的讲解(超喜欢这个博主的!) 网上找的另外一篇讲解 @0.5 - 你所需要了解的线性代数知识@ 什么是矩阵

HDU 4305 Lightning Matrix Tree定理

题目链接:https://vjudge.net/problem/HDU-4305 解法:首先是根据两点的距离不大于R,而且中间没有点建立一个图.之后就是求生成树计数了. Matrix-Tree定理(Kirchhoff矩阵-树定理).Matrix-Tree定理是解决生成树计数问题最有力的武器之一.它首先于1847年被Kirchhoff证明.在介绍定理之前,我们首先明确几个概念: 1.G的度数矩阵D[G]是一个n*n的矩阵,并且满足:当i≠j时,dij=0:当i=j时,dij等于vi的度数. 2.G

矩阵树定理(Matrix Tree)学习笔记

如果不谈证明,稍微有点线代基础的人都可以在两分钟内学完所有相关内容.. 行列式随便找本线代书看一下基本性质就好了. 学习资源: https://www.cnblogs.com/candy99/p/6420935.html http://blog.csdn.net/Marco_L_T/article/details/72888138 首先是行列式对几个性质(基本上都是用数学归纳法证): 1.交换两行(列),行列式取相反数 2.由1.得若存在两行(列)完全相同则行列式为0 3.上(下)三角行列式即主

【BZOJ1002】【FJOI2007】轮状病毒 生成树计数推导。 Python代码

突然学了一小下Python 算是勉强会写点了. 至于这道题的题解,就是根据Matrix Tree定理,然后Kirchhoff矩阵高斯消元就好了, 不过这道题如果消去中心点的行和列做的话,矩阵会很规矩,然后貌似"手算"可以推出公式(VFK Orz,手算--) VFK's blog:http://vfleaking.blog.163.com/blog/static/17480763420119685112649/ 然后下面是Python代码,算是裸语法吧. n=int(raw_input(

生成树计数 Matrix-Tree 定理

一直都知道要用Matrix-Tree定理来解决生成树计数问题,但是拖到今天才来学.博主数学不好也只能跟着各位大佬博客学一下它的应用以及会做题,证明实在是不会. 推荐博客https://blog.csdn.net/u011815404/article/details/89091011(Matrix-Tree定理) https://blog.csdn.net/u011815404/article/details/99679527(写得无敌好的生成树计数了) 那么比较常见的生成树计数问题就三种:①生成

kuangbin带你飞 生成树专题 : 次小生成树; 最小树形图;生成树计数

第一个部分 前4题 次小生成树 算法:首先如果生成了最小生成树,那么这些树上的所有的边都进行标记.标记为树边. 接下来进行枚举,枚举任意一条不在MST上的边,如果加入这条边,那么肯定会在这棵树上形成一个环,如果还要维护处树的特点 那么就要在这个环上删去一条边,这样他还是树,删掉的边显然是这条链上权值最大边更可能形成次小生成树.那么就有2中方法可以做. 第一种PRIM在prim时候直接可以做出这个从I到J的链上权值最大的值MAX[i][j]; 同时可以用kruskal同样方式标记树边,然后DFS跑

【HDU 4408】Minimum Spanning Tree(最小生成树计数)

Problem Description XXX is very interested in algorithm. After learning the Prim algorithm and Kruskal algorithm of minimum spanning tree, XXX finds that there might be multiple solutions. Given an undirected weighted graph with n (1<=n<=100) vertex

WC2017游记 &amp; 能力残废康复计划

懒癌晚期的蒟蒻一年多没有更Blog了- 这次冬眠营去绍一省好好地游玩了一番,体验了一段时间的豪华自助餐,成功吃胖- 第一课堂的东西基本还是没吸收-听着觉得有点道理,结果过几分钟就忘了-可能最大的收获就是(又)体会到自己太弱了- 于是变成了吃饭冬眠旅游营- 顺便-松爷真是太强辣-(我多年卡常可能卡的是假常数-排序连一亿都跑不过-丢人-) 于是三题都拿了小暴力分-虚炸了-凭借手玩提答的一分刚好卡过线一分(看起来还是挺多人刚好80的) 然后就旅游到杭州学车大酒店某校区,摸了几天鱼之后就回来了- 最虚的

生成树计数

生成树计数就是统计一张图中一共有多少种构造生成树的方案. 大概要用到组合数学等等的数学知识. 以下内容均来自NOI2007国家集训队论文 周冬 <生成树的计数及其应用>: ------------------------- Matrix-Tree定理(Kirchhoff矩阵-树定理).Matrix-Tree定理是解决生成树计数问题最有力的武器之一.它首先于1847年被Kirchhoff证明.在介绍定理之前,我们首先明确几个概念: 1.G的度数矩阵D[G]是一个n*n的矩阵,并且满足:当i≠j时