基尔霍夫矩阵

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

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

2)度数矩阵 \(D\left [ G\right ]\):当 \(i\neq j\) 时,\(D\left [ i\right ]\left [ j\right ]=0\),当 \(i= j\) 时,\(D\left [ i\right ]\left [ j\right ]=点v的度数\)

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

4)基尔霍夫矩阵(Kirchhoff) \(K\left [ G\right ]\):也称拉普拉斯算子,其定义为 \(K\left [ G\right ]=D\left [ G\right ]-A\left [ G\right ]\),即:\(K\left [ i\right ]\left [ j\right ]=D\left [ i\right ]\left [ j\right ]-A\left [ i\right ]\left [ j\right ]\)

例如:

 

 

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\n",det(n));
58     }
59     return 0;
60 }

参考博客:here

posted @ 2020-05-04 10:56  swsyya  阅读(1025)  评论(0编辑  收藏  举报

回到顶部