基尔霍夫(kirchhoff)矩阵树定理

引入问题

  给n个点m条边的图,求该图的最小生成树个数。

定理内容

  我们对这个图构造两个矩阵,分别是这个图的连通矩阵和度数矩阵。连通矩阵 S 1 S1 S1的第 i i i行第 j j j列上的数字表示原无向图中编号为 i i i和编号为 j j j的两个点之间的边的条数。度数矩阵 S 2 S2 S2只有斜对角线上有数字,即只有第 i i i行第 i i i列上有数字,表示编号为i的点的度数是多少。我们将两个矩阵相减,即 S 2 − S 1 S2−S1 S2S1,我们记得到的矩阵为 T T T,我们将矩阵 T T T去掉任意一行和一列(一般情况去掉最后一行和最后一列的写法比较多)得到 T ′ T^′ T,最后生成树的个数就是这个矩阵 T ′ T^′ T的行列式。
——摘自:《矩阵树定理浅谈》

基尔霍夫矩阵

  定义:如果图 D D D有总共 N N N个点,那么图 D D D的基尔霍夫矩阵 G G G可以表示为:

   G i j = { d e g r e e ( i ) i = j − c n t ( i , j ) i ≠ j G_{ij}=\left\{ \begin{array}{rcl} & degree(i) & &{i=j}\\ &−cnt(i,j) & &{i \neq j}\\ \end{array}\right. Gij={degree(i)cnt(i,j)i=ji=j

   d e g r e e degree degree:结点i的度数
   c n t cnt cnt :两点之间的边数

解决问题的关键就是利用基尔霍夫矩阵。

以下假设图无重边,证明摘自:《生成树的计数及其应用》周冬

性质
  • ∣ G ∣ = 0 \left|G\right|=0 G=0,证明:显然每行的和为0,把所有列都加到第一列得0。
  • 若图 D D D不连通,则其对应的基尔霍夫矩阵的任意 n − 1 n-1 n1阶主子式为0。

  证明:假设图 D D D k ( k > 1 ) k(k>1) k(k>1)个连通份量 D 1 , D 2 , . . . , D k D_1,D_2,...,D_k D1,D2,...,Dk。我们可以通过矩阵的变换使得这些连通分量的排列如下:(每次变换行列都交换一次,对应行列式符号不变)

     ( D 1 0 ⋯ 0 0 D 2 ⋯ 0 ⋮ ⋮ ⋱ ⋮ 0 0 0 D k ) \begin{pmatrix} D_1 & 0 &\cdots& 0\\\\ 0 & D_2 &\cdots&0\\\\ \vdots &\vdots & \ddots&\vdots\\\\ 0 & 0 & 0 &D_k\\\\ \end{pmatrix} D1000D20000Dk(矩阵中的0元素确保连通分量之间不连通)

   ∣ G ∣ \left|G\right| G= ∣ G 1 ∣ \left|G_1\right| G1 ∣ G 2 ∣ ⋯ ∣ G k ∣ \left|G_2\right|\cdots\left|G_k\right| G2Gk,据此可得出对应基尔霍夫矩阵的任意 n − 1 n-1 n1阶主子式为0。

  • 若图 D D D是树,其对应基尔霍夫矩阵 G G G的任意一个 n − 1 n-1 n1阶主子式为1。
     证明:往证,可以不断变换 ∣ G ∣ \left|G\right| G得到一上三角行列式,且主对角线元素为1。
     第一步:假设 v r v_r vr为根结点,以 v r v_r vr为首让每个结点根据与 v r v_r vr的距离从小到大排序,同距离的可任意排。显然对于结点 v j v_j vj,其父亲 v i v_i vi必定在前面。
     第二步:将 ∣ G ∣ \left|G\right| G根据排好的序列调整行列元素,将行列不断交换。因为交换为偶数次,符号不变。此外继续调整,对每个结点 v i v_i vi的儿子 v i 1 , v i 2 , . . . , v i k v_{i_1},v_{i_2},...,v_{i_k} vi1,vi2,...,vik,儿子对应的每一列都加到第 i i i列上。
     第三步:对于最后一列,对应结点只与父亲相连,故度为1,符合条件。用数学归纳法,目前处理的是第 i i i列,假设第 i + 1 i+1 i+1到第 n n n列都已经符合条件,即对角线元素为1。对每个结点 v i v_i vi的儿子 v i 1 , v i 2 , . . . , v i k v_{i_1},v_{i_2},...,v_{i_k} vi1,vi2,...,vik,其对应列的第 i i i行元素为-1,第 i j i_j ij行(对角线)的元素为1,再看第 i i i列,对应的儿子行元素都为-1,第 i i i行元素为 k + 1 k+1 k+1(儿子和父亲),故都加到第 i i i列后,第 i i i行元素变为1,下面每行都为0。因此,最终构造了上三角行列式且主对角元素为1,任意抽去第 i i i行第 i i i列,行列式值为1,证毕。

定理证明

引入定义,矩阵 B B B n × m n\times m n×m矩阵,分别对应结点和边。
   B i j = { − 1 v i 为 边 e j 起 点 1 v i 为 边 e j 终 点 0 o t h e r w i s e B_{ij}=\left\{ \begin{array}{rcl} & -1 & &v_i为边e_j起点\\ &1 & &v_i为边e_j终点\\ &0 & &otherwise\\ \end{array}\right. Bij=110viejviejotherwise

容易验证: B B T = G BB^T=G BBT=G,若去掉 B B B中第 r r r行得到 B r B_r Br,有 G r = B r B r T G_r=B_rB_r^T Gr=BrBrT,即 G G G去掉第 r r r行和第 r r r列。

看一下Binet-Cauchy公式:

设矩阵 A A A p × q p\times q p×q矩阵,矩阵 B B B q × p q\times p q×p矩阵,有

d e t ( A B ) = { 0 当 p > q 时 d e t ( A ) d e t ( B ) 当 p = q 时 ∑ 1 ≤ j 1 < j 2 < ⋯ < j p ≤ q A ( 1 2 ⋯ p j 1 j 2 ⋯ j p ) B ( j 1 j 2 ⋯ j p 1 2 ⋯ p ) 当 p < q 时 det(AB)=\left\{ \begin{array}{rcl} &0& 当p>q时\\ &det(A)det(B)& 当p=q时\\ & \sum\limits_{1\leq j_1<j_2<\cdots<j_p\leq q} A\begin{pmatrix} 1 &2&\cdots&p\\\\ j_1&j_2&\cdots&j_p \end{pmatrix} B\begin{pmatrix} j_1&j_2&\cdots&j_p\\\\ 1&2&\cdots&p \end{pmatrix} &当p<q时\\ \end{array}\right. det(AB)=0det(A)det(B)1j1<j2<<jpqA1j12j2pjpBj11j22jppp>qp=qp<q

其中 A ( 1 2 ⋯ p j 1 j 2 ⋯ j p ) A\begin{pmatrix} 1 &2&\cdots&p\\\\ j_1&j_2&\cdots&j_p \end{pmatrix} A1j12j2pjp表示 A A A的第 j 1 , j 2 , . . . , j p j_1,j_2,...,j_p j1,j2,...,jp列所成的子式, B ( j 1 j 2 ⋯ j p 1 2 ⋯ p ) B\begin{pmatrix} j_1&j_2&\cdots&j_p\\\\ 1&2&\cdots&p \end{pmatrix} Bj11j22jpp表示 B B B的第 j 1 , j 2 , . . . , j p j_1,j_2,...,j_p j1,j2,...,jp行所成的子式。

从而得到:

d e t ( G r ) = d e t ( B r B r T ) = ∑ x ⊂ { 1 , 2 , . . , m } ∣ x ∣ = n − 1 d e t ( B r x B r x T ) = ∑ x ⊂ { 1 , 2 , . . , m } ∣ x ∣ = n − 1 ( d e t ( B r x ) ) 2 det(G_r)=det(B_rB_r^T)=\sum\limits_{x\subset \{1,2,..,m\}\atop\left|x\right|=n-1}det(B_r^xB_r^{x^T})=\sum\limits_{x\subset \{1,2,..,m\}\atop\left|x\right|=n-1}(det(B_r^x))^2 det(Gr)=det(BrBrT)=x=n1x{1,2,..,m}det(BrxBrxT)=x=n1x{1,2,..,m}(det(Brx))2

解释一下: B r B_r Br ( n − 1 ) × m (n-1)\times m (n1)×m矩阵( m > n − 1 m>n-1 m>n1),则 d e t ( B r B r T ) = det(B_rB_r^T)= det(BrBrT)=所有 n − 1 n-1 n1列构成的子式的行列式的平方和。

B r x B_r^x Brx表示 B r B_r Br中边元素属于包含于边集 E E E的子集 x x x的所在列抽出构成的新矩阵,显然 B r x B r x T B_r^xB_r^{x^T} BrxBrxT可以看作一个 n n n个点和 n − 1 n-1 n1条边构成的图的基尔霍夫矩阵的的一个 n − 1 n-1 n1阶主子式,当 x x x为树时,行列式值为1,否则图不连通值为0,考察所有边集元素个数为 n − 1 n-1 n1的子集,结果就恰好为生成树个数!

对于含重边的图该定理仍然适用,但是如何证明尚且不知…

应用部分

模板题:P4111 [HEOI2015]小 Z 的房间

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const ll mod = 1e9;
const int dir[4][2] = { {1,0},{0,1}};
int n, m;
char g[10][10];
ll K[100][100];
int id[10][10];
void update(int x, int y) {
	K[x][y]--; K[y][x]--;
	K[x][x]++; K[y][y]++;
}
ll det(int n) {
	ll res = 1;
	for (int i = 1; i <= n; i++) {//依次把第i列,从第i+1行到第n行变为0
		for (int j = i + 1; j <= n; j++) {
			while (K[j][i]) {//直到为0
				ll t = K[i][i] / K[j][i];//计算第i列,第i行是第j行的几倍
				for (int k = i; k <= n; k++) {
					K[i][k] = (K[i][k] - t * K[j][k] % mod + mod) % mod;
					swap(K[i][k], K[j][k]);//把第i行元素变为0后与第j行交换
				}
				res = -res;//每次交换行 值变为原来的负数
			}
		}
		if (!K[i][i])return 0;
		res = (res * K[i][i] % mod + mod) % mod;//将行列式化为上三角行列式后 值为对角线元素的乘积
	}
	return res;
}
char read() {
	char ch = getchar();
	while (ch != '.' && ch != '*')ch = getchar();
	return ch;
}
int main(void) {
	memset(K, 0, sizeof(K));
	memset(id, 0, sizeof(id));
	scanf("%d %d", &n, &m);
	int cnt = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			g[i][j] = read();
			if (g[i][j] == '.')id[i][j] = ++cnt;
		}
	}
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			if (g[i][j] == '.') {
				if (id[i - 1][j])update(id[i - 1][j], id[i][j]);
				if (id[i][j - 1])update(id[i][j - 1], id[i][j]);
			}
	printf("%lld\n", det(cnt - 1) % mod);
	return 0;
}
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JILIN.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值