基尔霍夫矩阵

Matrix-Tree 定理又称基尔霍夫矩阵树定理,其用于解决:给定 n 个点 m 条边的无向图,求图的生成树个数的问题。

【基尔霍夫矩阵】
1.基本定义
1)无向图 (G):给定 (n) 个点,(m) 条边的无向图,设点集为 (V),边集为 (E),则其记为 (Gleft ( V,E ight ))

2)度数矩阵 (Dleft [ G ight ]):当 (i eq j) 时,(Dleft [ i ight ]left [ j ight ]=0),当 (i= j) 时,(Dleft [ i ight ]left [ j ight ]=点v的度数)

3)邻接矩阵 (Aleft [ G ight ]):当 (v_{i})、(v_{j}) 有边连接时,(Aleft [ i ight ]left [ j ight ]=1),当 (v_{i})、(v_{j}) 无边连接时,(Aleft [ i ight ]left [ j ight ]=0)

4)基尔霍夫矩阵(Kirchhoff) (Kleft [ G ight ]):也称拉普拉斯算子,其定义为 (Kleft [ G ight ]=Dleft [ G ight ]-Aleft [ G ight ]),即:(Kleft [ i ight ]left [ j ight ]=Dleft [ i ight ]left [ j ight ]-Aleft [ i ight ]left [ j ight ])

例如:

2.基尔霍夫矩阵性质
对于任意一个图 (G),其基尔霍夫矩阵 (K) 具有以下性质:

1.基尔霍夫矩阵 (K) 的每一行或每一列上的元素和都是 (0)
2.基尔霍夫矩阵 (K) 的行列式的值为 (0)
3.基尔霍夫矩阵 (K) 的任意一个代数余子式值都相同
4.如果图 (G) 不连通,基尔霍夫矩阵 (K) 的任意主子式行列式值为 (0)
5.如果图 (G) 是一棵树,基尔霍夫矩阵 (K) 的任意一个 (n-1) 阶主子式的行列式为 (1)


3.Matrix-Tree 定理
Matrix-Tree 定理的内容为:对于已经得出的基尔霍夫矩阵,去掉其随意一行一列得出的矩阵的行列式,其绝对值为生成树的个数

因此,对于给定的图 (G),若要求其生成树个数,可以先求其基尔霍夫矩阵,然后随意取其任意一个 (n-1) 阶行列式,然后求出行列式的值,其绝对值就是这个图中生成树的个数

基尔霍夫矩阵裸题:here

 

 模板:(AC_Code)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 20;
 5 const int inf = 0x3f3f3f3f;
 6 #define rep(i,first,second) for(ll i=first;i<=second;i++)
 7 #define dep(i,first,second) for(ll i=first;i<=second;i++)
 8 int degree[maxn];
 9 ll a[maxn][maxn];
10 int vis[maxn][maxn];
11 
12 void init(){
13     memset(degree,0,sizeof(degree));
14     memset(a,0,sizeof(a));
15     memset(vis,0,sizeof(vis));
16 }
17 
18 ll det(int n){
19     ll ret=1;
20     for(int i=2;i<=n;i++){
21         for(int j=i+1;j<=n;j++){
22             while(a[j][i]){
23                 ll t=a[i][i]/a[j][i];
24                 for(int k=i;k<=n;k++){
25                     a[i][k]=(a[i][k]-a[j][k]*t);
26                 }
27                 for(int k=i;k<=n;k++){
28                     swap(a[i][k],a[j][k]);
29                 }
30                 
31                 ret=-ret;
32             }
33         }
34         if( a[i][i]==0 ) return 0;
35         ret*=a[i][i];
36     }
37     if( ret<0 ) ret=-ret;
38     return ret;
39 }
40 
41 int main()
42 {
43     int t;
44     scanf("%d",&t);
45     while( t-- ){
46         init();
47         int n,m;
48         scanf("%d%d",&n,&m);
49         while( m--){
50             int u,v;
51             scanf("%d%d",&u,&v);
52             a[u][u]++;
53             a[v][v]++;
54             a[u][v]--;
55             a[v][u]--;
56         }
57         printf("%lld
",det(n));
58     }
59     return 0;
60 }

参考博客:here

原文地址:https://www.cnblogs.com/wsy107316/p/12825699.html