1. 程式人生 > 實用技巧 >Notes: Kirchhoff's Matrix 基爾霍夫矩陣

Notes: Kirchhoff's Matrix 基爾霍夫矩陣

Notes: Kirchhoff's Matrix 基爾霍夫矩陣


一般說來,我部落格裡的 \(\LaTeX\) 通常都沒什麼用。不過我很高興,但是這回不是了。


眾所周知地,基爾霍夫矩陣(Kirchhoff's Matrix)是用以解決圖上生成樹計數問題的。

接下來我們分有向圖無向圖的情況考慮一下。



無向圖上的基爾霍夫矩陣


Theorem

考慮一個含有 \(n\) 個點的無向圖 \(G\),我們定義度數矩陣 \(D(G)\) 為:

\[\large D(G)_{ij} = \cases{ 0 & $i \not=j$ \\ \deg(i) & $i =j$ } \]

其中 \(\deg(i)\)

是結點 \(i\) 的度數。

我們定義鄰接矩陣 \(A(G)\) 為:

\[\large A(G)_{i,j} = \cases { {\rm edg}(i,j) & $i \not= j$ \\ 0 & $i = j$ } \]

其中 \({\rm edg}(i, j)\) 是結點 \(i\) 與結點 \(j\) 之間連邊的數量。

(這顯然是我們考慮生成樹問題時的關鍵指標嘛


矩陣樹定理指出,如果我們定義基爾霍夫矩陣 \(K(G)\) 為:

\[\large K(G) = D(G) - A(G) \]

那麼,取 \(K(G)\) 的任一 \(n - 1\) 階主子式 \(K'(G) = K(G) \begin{pmatrix} 1 & \dots & i - 1 & i + 1 & \dots n \\ 1 & \dots & i - 1 & i + 1 & \dots n \end{pmatrix}\)

我們有生成樹個數 \(ans\) 就是 \(K'\) 的行列式,也即是說:

\[\large ans = \det (K'(G)) \]

等價地,設 \(\lambda_1,\lambda_2,\dots,\lambda_{n-1}\)\(K(G)\)\(n - 1\) 個非零特徵值,我們也有:

\[\large ans = \frac{1}{n}\cdot \prod _ {i = 1} ^ {n - 1} \lambda_i \]

證明留給讀者(逃

Hints

主子式:

\(K'(G) = K(G) \begin{pmatrix} 1 & \dots & i - 1 & i + 1 & \dots n \\ 1 & \dots & i - 1 & i + 1 & \dots n \end{pmatrix}\)

表示取矩陣 \(K(G)\)

\(1,\dots,i-1,i+1,\dots,n\) 行,與第 \(1,\dots,i-1,i+1,\dots,n\) 構成的子矩陣。

取出 \(k\)\(k\) 列的子矩陣被稱為原矩陣的 \(k\) 階主子式。


行列式的求法:

定義是這樣:

\[\large \det(A) = \sum_{s \in S} {\rm sgn}(s) \cdot\prod_{i=1}^n A_{i,s_i} \]

其中 \(S\) 是所有 \(1\sim n\) 的排列構成的集合,\(s_i\) 表示排列 \(s\) 中的第 \(i\) 個數。

其中 \({\rm sgn}(s)\) 表示 \(s\) 中逆序對數量的奇偶性,奇數為 0 ,偶數為 1 。


這個定義複雜得幾乎不可求,有時我們會選擇將行列式展開求解:

考慮行列式:

\[\large A = \begin{vmatrix} a_{11} & a_{12} & \dots & a_{1n} \\ a_{21} & a_{22} & \dots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{n1} & a_{n2} & \dots & a_{nn} \end{vmatrix} \]

我們把 \(A\) 的第 \(i\) 行與第 \(j\) 列去掉後留下了的行列式稱為 \(a_{ij}\) 的餘子式,記作 \(M_{ij}\)

然後定義一個叫做代數餘子式的東西 \(A_{ij} = (-1)^{i+j} M_{ij}\)

如果選定固定的一行 \(k\) ,行列式的值 \(D\) 就滿足

\[\large D = \sum _ {j = 1} ^ n a_{kj}\cdot A_{kj} \]

選定固定的一行 \(k\) 也是一樣的:

\[\large D = \sum _ {i = 1} ^ n a_{ik}\cdot A_{ik} \]

證明顯然。

不過行列式展開還是太煩了,我們還有別的招。

我們知道行列式有個性質,就是考慮行列式 \(A\) 的任意兩個行向量 \(v_i,v_j\) (列向量也一樣,略)

若進行操作令 \(v_i = v_i + k \cdot v_j\) 行列式的值不變。

於是我們可以高斯消元把原行列式化成行列梯式(簡單理解為對角線的某一側全都是 0 )

顯然,

\[\large D = \prod _ {i = 1} ^ n a'_{ii} \]

這個複雜度是 \(O(n^3)\) 的,完全可以接受。

class Matrix {
#define rep(a, b, c) for(int a = b; a <= c; ++a)
private:
	vector<vector<double> > mat;

public:
	inline void init(int n) {
		mat.resize(n + 1);
		for(int i = 1; i <= n; ++i)
			mat[i].resize(n + 1);
	}

	int length() {
		return mat.size() - 1;
	}

	double &operator () (int i, int j) {
		return mat[i][j];
	}

	double det() {
		int n = length();

		rep(i, 1, n) {
			int p = i;
			rep(j, i + 1, n)
				if(fabs(mat[j][i]) > fabs(mat[p][i])) p = j;
			if(p != i) {
				rep(j, i ,n) swap(mat[i][j], mat[p][j]);
			}
			rep(j, i + 1, n) {
				double tmp = mat[j][i] / mat[i][i];
				rep(k, 1, n) mat[j][k] -= mat[i][k] * tmp;
			}
		}

		double ans = 1;
		for(int i = 1; i <= n; ++i)
			ans *= mat[i][i];
		return ans;
	}
};

特徵值的求法:

其實我不太會。上網找到一篇 https://zhuanlan.zhihu.com/p/61363638 大家可以參考。



有向圖上的基爾霍夫矩陣


Theorem

有向圖上結點的度分為入度和出度,很自然地,我們定義入度矩陣和出度矩陣:

\[\large D(G)_{ij}^{\rm out} = \cases{ 0 & $i \not=j$ \\ {\rm deg^{out}}(i) & $i =j$ } \\[1cm] \large D(G)_{ij}^{\rm in} = \cases{ 0 & $i \not=j$ \\ {\rm deg^{in}}(i) & $i =j$ } \]

不用說,其中 \({\rm deg^{out}}(i)\) 為結點 \(i\) 的出度,\({\rm deg^{in}}(i)\) 為結點 \(i\) 的入度。

鄰接矩陣定義不變:

\[\large A(G)_{i,j} = \cases { {\rm edg}(i,j) & $i \not= j$ \\ 0 & $i = j$ } \]

同樣定義出入度基爾霍夫矩陣:

\[\large K(G)^{\rm out} = D(G)^{\rm out} - A(G) \\[0.4cm] \large K(G)^{\rm in} = D(G)^{\rm in} - A(G) \]

接下來……

等等,還沒定義有向圖上的生成樹吧?

我們記 \(ans_f\) 表示所有邊都從兒子指向父親的生成樹個數, \(ans_s\) 表示所有邊都從父親指向兒子的生成樹個數。

類似地有:

\[\large \begin{align*} ans_f(i) =\det(~~ K(G)^{\rm out} &\begin{pmatrix} 1 & \dots & i - 1 & i + 1 & \dots n \\ 1 & \dots & i - 1 & i + 1 & \dots n \end{pmatrix} ~~) \\[0.2cm] ans_s(i) =\det(~~ K(G)^{\rm in~} &\begin{pmatrix} 1 & \dots & i - 1 & i + 1 & \dots n \\ 1 & \dots & i - 1 & i + 1 & \dots n \end{pmatrix} ~~) \end{align*} \]

其中 \(i\) 是根節點的編號,求總數你得列舉做 \(\sum\)

證明留給讀者。