• 使用Matrix-tree与它的行列式来解决生成树计数问题


    我又把Matrix写错啦


    这东西讲课的时候竟然一笔带过了,淦

    好吧这东西我不会证

    那我们来愉快的看结论吧

    啦啦啦

    预备工作

    你有一个 $ n $ 个点的图

    比如说

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

    现在造一个$ n imes n $的矩阵

    我们把他叫做$ D $

    $ D $的元素有这样的一个规律:

    对于某一个$ D_{i,j} $,如果 $ i = j $ ,它就等于点 $ i $ 的度数,否则就为 $ 0 $

    那么我们可以yy出D的样子

    [ D=left[ egin{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} ight] ]

    除此之外我们还需要一个矩阵$ A $

    就是邻接矩阵,直接拿来用就可以了

    [ A=left[ egin{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} ight] ]

    Now I have a D

    I have an A

    Ah~

    $ D - A $!

    [ D-A=left[ egin{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} ight] ]

    依照数学的一贯尿性习惯

    我们把$ D - A $起个名字吧

    叫做鸡儿hop夫基尔霍夫Kirchhoff矩阵K,$ K = D - A $

    关于行列式

    对于一个无向图 G ,它的生成树个数等于其基尔霍夫Kirchhoff矩阵任何一个N-1阶主子式的行列式的绝对值

    上面那个是真-结论

    你问我什么是行列式?

    我们本来写矩阵不是

    [ K=left[ egin{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} ight] ]

    的么

    我们把$ [ ] $换成 $ | | $ 就好了
    (这可能不符合数学的严谨性)
    (只在矩阵$ n = m $时有效)

    [ K=left| egin{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} ight| ]

    了解更多

    你问我什么是$ x $阶主子式?

    就在 $ [1,n] $ 里面随便选个数 $ p $ ,选 $ (n-x) $ 次,把行列式里面的第 $ p $ 行和第 $ p $ 列同时删掉就好了

    比如 $ K $ 的某个 $ n - 1 $ 阶主子式长这样:

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

    行列式求值的问题

    行列式的值记为$ det(A) $

    方法你们都看过了

    就是

    • 枚举 $ [1,n] $ 的所有排列,把它叫做 $ b $
    • 把 $ b $ 的逆序对数量求出来叫做 $ r $
    • 然后 $ det(A) = sum (-1)^{r} imes A_{1,b_{1}} imes A_{2,b_{2}} imes ... imes 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;
    }
    
  • 相关阅读:
    LeetCode 811. Subdomain Visit Count (子域名访问计数)
    LeetCode 884. Uncommon Words from Two Sentences (两句话中的不常见单词)
    LeetCode 939. Minimum Area Rectangle (最小面积矩形)
    LeetCode 781. Rabbits in Forest (森林中的兔子)
    LeetCode 739. Daily Temperatures (每日温度)
    三种方式实现按钮的点击事件
    239. Sliding Window Maximum
    14.TCP的坚持定时器和保活定时器
    13.TCP的超时与重传
    12.TCP的成块数据流
  • 原文地址:https://www.cnblogs.com/finder-iot/p/8662187.html
Copyright © 2020-2023  润新知