版权声明:2018/4/10重启blog;转载请注明出处 https://blog.csdn.net/zhaiqiming2010/article/details/81503613
矩阵树定理的作用?
主要用来解决生成树计数问题
准备
对于给定的无向图G
定义度数矩阵D[G] 满足:当i≠j时,dij=0;当i=j时,dij等于vi的度数。
定义邻接矩阵A[G] 满足:当i≠j时,如果节点i和节点j之间存在边,dij=1;当i=j时,dij = 0。
定义给定的无向图G的基尔霍夫矩阵C[G] = D[G] - A[G]。
G的生成树的个数 = C[G]任何一个n-1阶主子式的行列式的绝对值。
证明
1.基尔霍夫矩阵的行列式一定都是0,因为基尔霍夫矩阵的任意行或列的和都是0。
2.如果G是不连通的,则它的基尔霍夫矩阵的任一个主子式的行列式均为0。
当G不连通的时候,G中存在多个联通分量,将存在于同一个联通分量的点通过交换行和列使其相邻,假设存在K(k>1)个联通分量,行交换的次数为x次,那么列交换的次数一定也为x次,总交换次数为2*x次,所以矩阵的符号不变。
交换完成之后如图(图片来自 周东《生成树的计数及其应用》)
图中的框中的G1...Gk都代表在给出的G中的联通分量的基尔霍夫矩阵,所以|C[G1]| .... |C[Gk]|都为0。
所以对于n-1阶主子式的行列式,对角线求乘积,除了去掉的一行一列所在的矩阵,其余的矩阵的行列式的值都为0,所以n-1阶主子式的行列式的值为0。
3.如果G是一颗树,那么它的Kirchhoff矩阵C的任一个n-1阶主子式的行列式均为1。
O(n^3)高斯消元计算行列式的值
bool zero(double a)
{
return a>-eps && a<eps;
}
double Gauss()
{
double mul,Result=1;
int i,j,k,b[n];
for(i=0;i<n;i++) b[i]=i;
for(i=0;i<n;i++){
if(zero(a[b[i]][i]))
for(j=i+1;j<n;j++)
if(!zero(a[b[j]][i])) { swap(b[i],b[j]); Result*=-1; break; }
Result*=a[b[i]][i];
for(j=i+1;j<n;j++)
if(!zero(a[b[j]][i])){
mul=a[b[j]][i]/a[b[i]][i];
for(k=i;k<n;k++)
a[b[j]][k]-=a[b[i]][k]*mul;
}
}
return Result;
}
参考资料:周东《生成树的计数及其应用》