使用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;
}
posted @ 2018-03-28 10:10  iot;  阅读(655)  评论(10编辑  收藏  举报
知识共享许可协议
年轻人,你需要更多的知识