使用Matrix-tree與它的行列式來解決生成樹計數問題


我又把Matrix寫錯啦


這東西講課的時候竟然一筆帶過了,淦

好吧這東西我不會證

那我們來愉快的看結論吧

啦啦啦

預備工作

你有一個 $ n $ 個點的圖

比如說

   5
  /|\
 / | \
2--1--3
    \ |
     \|
      4

現在造一個$ n \times n $的矩陣

我們把他叫做$ D $

$ D $的元素有這樣的一個規律:

對於某一個$ D_{i,j} $,如果 $ i = j $ ,它就等於點 $ i $ 的度數,否則就為 $ 0 $

那么我們可以yy出D的樣子

\[ D=\left[ \begin{matrix} 4 & 0 & 0 & 0 & 0 \\ 0 & 2 & 0 & 0 & 0 \\ 0 & 0 & 3 & 0 & 0 \\ 0 & 0 & 0 & 2 & 0 \\ 0 & 0 & 0 & 0 & 3 \\ \end{matrix} \right] \]

除此之外我們還需要一個矩陣$ A $

就是鄰接矩陣,直接拿來用就可以了

\[ A=\left[ \begin{matrix} 0 & 1 & 1 & 1 & 1 \\ 1 & 0 & 0 & 0 & 1 \\ 1 & 0 & 0 & 1 & 1 \\ 1 & 0 & 1 & 0 & 0 \\ 1 & 1 & 1 & 0 & 0 \\ \end{matrix} \right] \]

Now I have a D

I have an A

Ah~

$ D - A $!

\[ D-A=\left[ \begin{matrix} 4 & -1 & -1 & -1 & -1 \\ -1 & 2 & 0 & 0 & -1 \\ -1 & 0 & 3 & -1 & -1 \\ -1 & 0 & -1 & 2 & 0 \\ -1 & -1 & -1 & 0 & 3 \\ \end{matrix} \right] \]

依照數學的一貫尿性習慣

我們把$ D - A $起個名字吧

叫做雞兒hop夫基爾霍夫Kirchhoff矩陣K,$ K = D - A $

關於行列式

對於一個無向圖 G ,它的生成樹個數等於其基爾霍夫Kirchhoff矩陣任何一個N-1階主子式的行列式的絕對值

上面那個是真-結論

你問我什么是行列式?

我們本來寫矩陣不是

\[ K=\left[ \begin{matrix} 4 & -1 & -1 & -1 & -1 \\ -1 & 2 & 0 & 0 & -1 \\ -1 & 0 & 3 & -1 & -1 \\ -1 & 0 & -1 & 2 & 0 \\ -1 & -1 & -1 & 0 & 3 \\ \end{matrix} \right] \]

的么

我們把$ [ ] $換成 $ | | $ 就好了
(這可能不符合數學的嚴謹性)
(只在矩陣$ n = m $時有效)

\[ K=\left| \begin{matrix} 4 & -1 & -1 & -1 & -1 \\ -1 & 2 & 0 & 0 & -1 \\ -1 & 0 & 3 & -1 & -1 \\ -1 & 0 & -1 & 2 & 0 \\ -1 & -1 & -1 & 0 & 3 \\ \end{matrix} \right| \]

了解更多

你問我什么是$ x $階主子式?

就在 $ [1,n] $ 里面隨便選個數 $ p $ ,選 $ (n-x) $ 次,把行列式里面的第 $ p $ 行和第 $ p $ 列同時刪掉就好了

比如 $ K $ 的某個 $ n - 1 $ 階主子式長這樣:

\[ tmp=\left| \begin{matrix} 4 & -1 & -1 & -1 \\ -1 & 2 & 0 & 0 \\ -1 & 0 & 3 & -1 \\ -1 & 0 & -1 & 2 \\ \end{matrix} \right| \]

行列式求值的問題

行列式的值記為$ det(A) $

方法你們都看過了

就是

  • 枚舉 $ [1,n] $ 的所有排列,把它叫做 $ b $
  • 把 $ b $ 的逆序對數量求出來叫做 $ r $
  • 然后 $ det(A) = \sum (-1)^{r}\times A_{1,b_{1}}\times A_{2,b_{2}}\times ... \times A_{n,b_{n}} $

不過這樣的復雜度肯定非常高

但我們有一種更好的方法

我們可以利用行列式的這些性質:

  • 行列式 $ A $ 中某行/列用同一數 $ k $ 乘,其det結果等於 $ kA $
  • 行列式 $ A $ 的det等於其轉置行列式 $ A^T $ 的( $ A^T $ 的第i行為 $ A $ 的第i列)
  • 行列式 $ A $ 中兩行/列互換,其det會變成原來的相反數。
  • 把行列式 $ A $ 的某行/列中各個數同乘一數后加到另一行/列中各對應數上,結果不會變
  • 行列式中某行/列有公因子,這個公因子可以提到行列式外面去

來把行列式變成上三角行列式(其實下三角也一樣)

去看一看上三角行列式

至於怎么用我們親愛的C++來寫這東西

實現起來就是這個樣子(*內部寫了取模)

typedef long long lint;
const int _ = 202;
lint deter(lint a[_][_],int n,lint mo)
{
	register int i,j,k;
	register lint tmp,ans=1;
	for(i=1;i<=n;i++)for(j=1;j<=n;j++)a[i][j]%=mo;
	for(i=1;i<=n;i++)
	{
		for(j=i+1;j<=n;j++)
		{
			while(a[j][i]!=0)
			{
				tmp=a[i][i]/a[j][i];
				for(k=1;k<=n;k++)a[i][k]=(a[i][k]-a[j][k]*tmp+mo)%mo;
				swap(a[i],a[j]),ans=-ans;
			}
		}
		ans=(ans*a[i][i]+mo)%mo;
		if(ans==0)return 0;
	}
	return (ans+mo)%mo;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM