Notes: Kirchhoff's Matrix 基尔霍夫矩阵
一般说来,我博客里的 (LaTeX) 通常都没什么用。不过我很高兴,这回不是了。
众所周知地,基尔霍夫矩阵(Kirchhoff's Matrix)是用以解决图上生成树计数问题的。
接下来我们分有向图无向图的情况考虑一下。
无向图上的基尔霍夫矩阵
Theorem
考虑一个含有 (n) 个点的无向图 (G),我们定义度数矩阵 (D(G)) 为:
其中 (deg(i)) 是结点 (i) 的度数。
我们定义邻接矩阵 (A(G)) 为:
其中 ({ m edg}(i, j)) 是结点 (i) 与结点 (j) 之间连边的数量。
(这显然是我们考虑生成树问题时的关键指标嘛
矩阵树定理指出,如果我们定义基尔霍夫矩阵 (K(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') 的行列式,也即是说:
等价地,设 (lambda_1,lambda_2,dots,lambda_{n-1}) 是 (K(G)) 的 (n - 1) 个非零特征值,我们也有:
证明留给读者(逃
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) 阶主子式。
行列式的求法:
定义是这样:
其中 (S) 是所有 (1sim n) 的排列构成的集合,(s_i) 表示排列 (s) 中的第 (i) 个数。
其中 ({ m sgn}(s)) 表示 (s) 中逆序对数量的奇偶性,奇数为 0 ,偶数为 1 。
这个定义复杂得几乎不可求,有时我们会选择将行列式展开求解:
考虑行列式:
我们把 (A) 的第 (i) 行与第 (j) 列去掉后留下了的行列式称为 (a_{ij}) 的余子式,记作 (M_{ij}) 。
然后定义一个叫做代数余子式的东西 (A_{ij} = (-1)^{i+j} M_{ij}) ,
如果选定固定的一行 (k) ,行列式的值 (D) 就满足
选定固定的一行 (k) 也是一样的:
证明显然。
不过行列式展开还是太烦了,我们还有别的招。
我们知道行列式有个性质,就是考虑行列式 (A) 的任意两个行向量 (v_i,v_j) (列向量也一样,略)
若进行操作令 (v_i = v_i + k cdot v_j) 行列式的值不变。
于是我们可以高斯消元把原行列式化成行列梯式(简单理解为对角线的某一侧全都是 0 )
显然,
这个复杂度是 (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
有向图上结点的度分为入度和出度,很自然地,我们定义入度矩阵和出度矩阵:
不用说,其中 ({ m deg^{out}}(i)) 为结点 (i) 的出度,({ m deg^{in}}(i)) 为结点 (i) 的入度。
邻接矩阵定义不变:
同样定义出入度基尔霍夫矩阵:
接下来……
等等,还没定义有向图上的生成树吧?
我们记 (ans_f) 表示所有边都从儿子指向父亲的生成树个数, (ans_s) 表示所有边都从父亲指向儿子的生成树个数。
类似地有:
其中 (i) 是根节点的编号,求总数你得枚举做 (sum)
证明留给读者。