摘自大牛的见解

生成树

生成树(spanning-tree)是图论里面一个重要的概念。

一个无向图的所有边构成的集合称为这个无向图的边集,一个构成树的边集的子集,就成为这个无向图的生成树。 如果只是要求一棵生成树或者是要求边总权值最小的生成树,有很多经典的算法,比如Prim与Kruscal算法。 然而如果要求一个无向图的生成树数量,就不是一个那么简单的任务了。

Matrix-Tree定理

以下引用自国家集训队2008论文集

Matrix-Tree定理是解决生成树计数问题最有力的武器之一。它首先于1847年被Kirchhoff证明。在介绍定理之前,我们首先明确几个概念:

1、 G的度数矩阵D[G]是一个nn的矩阵,并且满足:当i≠j时,dij=0;当i=j时,dij等于vi的度数。 2、 G的邻接矩阵A[G]也是一个nn的矩阵, 并且满足:如果vi、vj之间有边直接相连,则aij=1,否则为0。

我们定义G的Kirchhoff矩阵(也称为拉普拉斯算子)C[G]为C[G]=D[G]-A[G],则Matrix-Tree定理可以描述为:G的所有不同的生成树的个数等于其Kirchhoff矩阵C[G]任何一个n-1阶主子式的行列式的绝对值。所谓n-1阶主子式,就是对于r(1≤r≤n),将C[G]的第r行、第r列同时去掉后得到的新矩阵,用Cr[G]表示。

The Matrix Revolutions(ICPC Regionals 2014 :: Asia - Shanghai Problem A)

给定一个无向图,每条边上有黑色或者白色,求黑色边数不超过K的生成树数量对10^9+7取模。 点数不超过50。

Matrix-Tree定理可以求出一个无向图的生成树数量,但这个问题似乎不能直接用Matrix-Tree定理解决,我们换个思路,如果把度数矩阵与邻接矩阵中的1换成代表颜色的字母代数xy。这样得到的行列式就有xy这两个未知元,此时行列式得到的值就是一个关于x与y的多项式。而且可以发现xayb的系数就是含有ax边以及by边的生成树数量。

由于一个生成树边的数量等于点的数量-1,意味着得到的多项式满足a+b+1=点数。也就是说可以让y=1,这样就可以少一个变元,简化接下来的运算。

暴力解一个行列式需要枚举所有全排列的情况,时间复杂度极高。然而可以使用高斯消元来对行列式进行初等变换成一个上三角矩阵,这样只需要O(n3)的时间复杂度来求一个行列式对一个质数的取模,n为行列式的阶数。

然而这回这个问题里面有x这个变元,意味着我们无法进行高斯消元。但是知道得到的值是关于xn阶多项式,可以考虑插值,把这个多项式的系数都计算出来,如果我们得到了所有系数,这个问题就迎刃而解了。

需要对一个n阶多项式插值,意味着至少需要知道n个这个多项式的取值。所以将x=0n1代入矩阵,分别解出对应的行列式,就能得到这些取值,时间复杂度为O(n4)

最后一步就是多项式插值,可以采用高斯消元或者拉格朗日插值法。 如果用高斯消元,系数矩阵是一个0n1的范德蒙矩阵,它的逆矩阵可以直接计算出来。 如果采用拉格朗日插值,需要构造出n个多项式,满足当x=i时值为1xi时值为0。对应取值的行向量与多项式构成的列向量做点积,就能得到这个行列式。

得到行列式之后,我们知道xi的系数就是有i条x边的生成树数量,所以只需将不超过K的系数之和计算出来就是答案。

原文地址:https://www.cnblogs.com/zxhl/p/4655956.html