zoukankan      html  css  js  c++  java
  • Notes: Kirchhoff's Matrix 基尔霍夫矩阵

    Notes: Kirchhoff's Matrix 基尔霍夫矩阵


    一般说来,我博客里的 (LaTeX) 通常都没什么用。不过我很高兴,这回不是了。


    众所周知地,基尔霍夫矩阵(Kirchhoff's Matrix)是用以解决图上生成树计数问题的。

    接下来我们分有向图无向图的情况考虑一下。



    无向图上的基尔霍夫矩阵


    Theorem

    考虑一个含有 (n) 个点的无向图 (G),我们定义度数矩阵 (D(G)) 为:

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

    其中 (deg(i)) 是结点 (i) 的度数。

    我们定义邻接矩阵 (A(G)) 为:

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

    其中 ({ m edg}(i, j)) 是结点 (i) 与结点 (j) 之间连边的数量。

    (这显然是我们考虑生成树问题时的关键指标嘛


    矩阵树定理指出,如果我们定义基尔霍夫矩阵 (K(G)) 为:

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

    那么,取 (K(G)) 的任一 (n - 1) 阶主子式 (K'(G) = K(G) egin{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) egin{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} { m sgn}(s) cdotprod_{i=1}^n A_{i,s_i} ]

    其中 (S) 是所有 (1sim n) 的排列构成的集合,(s_i) 表示排列 (s) 中的第 (i) 个数。

    其中 ({ m sgn}(s)) 表示 (s) 中逆序对数量的奇偶性,奇数为 0 ,偶数为 1 。


    这个定义复杂得几乎不可求,有时我们会选择将行列式展开求解:

    考虑行列式:

    [large A = egin{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}^{ m out} = cases{ 0 & $i ot=j$ \ { m deg^{out}}(i) & $i =j$ } \[1cm] large D(G)_{ij}^{ m in} = cases{ 0 & $i ot=j$ \ { m deg^{in}}(i) & $i =j$ } ]

    不用说,其中 ({ m deg^{out}}(i)) 为结点 (i) 的出度,({ m deg^{in}}(i)) 为结点 (i) 的入度。

    邻接矩阵定义不变:

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

    同样定义出入度基尔霍夫矩阵:

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

    接下来……

    等等,还没定义有向图上的生成树吧?

    我们记 (ans_f) 表示所有边都从儿子指向父亲的生成树个数, (ans_s) 表示所有边都从父亲指向儿子的生成树个数。

    类似地有:

    [large egin{align*} ans_f(i) =det(~~ K(G)^{ m out} &egin{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)^{ m in~} &egin{pmatrix} 1 & dots & i - 1 & i + 1 & dots n \ 1 & dots & i - 1 & i + 1 & dots n end{pmatrix} ~~) end{align*} ]

    其中 (i) 是根节点的编号,求总数你得枚举做 (sum)

    证明留给读者。

  • 相关阅读:
    [转载]Install Opera 12.16 Web Browser in CentOS/RHEL and Fedora
    [转载]CentOS 6.5 安装五笔输入法
    [转载]Lenovo E431 装Centos7无线驱动安装
    ElasticSearch的按日期排序问题
    [转载]java自带线程池和队列详细讲解
    [转载]Redis后台启动
    [转载]Process工具类,提供设置timeout功能
    [转载]使用java.lang.Process类的简单例子
    [转载]SecureCRT 绝佳配色方案, 保护你的眼睛
    4.二叉搜索树转为有序双向链表(递归算法与非递归算法)
  • 原文地址:https://www.cnblogs.com/Shimarin/p/13864197.html
Copyright © 2011-2022 走看看