我又把Matrix寫錯啦
這東西講課的時候竟然一筆帶過了,淦
好吧這東西我不會證
那我們來愉快的看結論吧
啦啦啦
預備工作
你有一個 $ n $ 個點的圖
比如說
5
/|\
/ | \
2--1--3
\ |
\|
4
現在造一個$ n \times n $的矩陣
我們把他叫做$ D $
$ D $的元素有這樣的一個規律:
對於某一個$ D_{i,j} $,如果 $ i = j $ ,它就等於點 $ i $ 的度數,否則就為 $ 0 $
那么我們可以yy出D的樣子
除此之外我們還需要一個矩陣$ A $
就是鄰接矩陣,直接拿來用就可以了
Now I have a D
I have an A
Ah~
$ D - A $!
依照數學的一貫尿性習慣
我們把$ D - A $起個名字吧
叫做雞兒hop夫基爾霍夫Kirchhoff矩陣K,$ K = D - A $
關於行列式
對於一個無向圖 G ,它的生成樹個數等於其基爾霍夫Kirchhoff矩陣任何一個N-1階主子式的行列式的絕對值
上面那個是真-結論
你問我什么是行列式?
我們本來寫矩陣不是
的么
我們把$ [ ] $換成 $ | | $ 就好了
(這可能不符合數學的嚴謹性)
(只在矩陣$ n = m $時有效)
你問我什么是$ x $階主子式?
就在 $ [1,n] $ 里面隨便選個數 $ p $ ,選 $ (n-x) $ 次,把行列式里面的第 $ p $ 行和第 $ p $ 列同時刪掉就好了
比如 $ K $ 的某個 $ n - 1 $ 階主子式長這樣:
行列式求值的問題
行列式的值記為$ 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;
}