矩阵树定理与BEST定理

行列式

定义:\(\det(A)\),又记作 \(\vert A\vert\),等于 \(\sum_p (-1)^{\tau(p)} \prod_{i = 1}^nA_{i, p_i}\),其中 \(p\)\(1 \sim n\) 的排列,\(\tau(p)\) 表示排列 \(p\) 的逆序对数。

1. 对于一个上三角矩阵,他的行列式等于主对角线所有值的乘积。

要使 \(A_{n, p_n} \ne 0\)\(p_n\) 只能取 \(n\);要使 \(A_{n - 1, p_{n - 1}} \ne 0\)\(p_{n - 1} \in \{n - 1, n\}\),但是 \(n\) 已经被用过了,\(p_{n - 1} = n - 1\)

以此类推,使 \(\prod A_{i, p_i}\) 非零的只有唯一一个排列 \(p_i = i\),此时 \(\tau(p) = 0\)

2. 单位矩阵的行列式为 \(1\),即 \(\vert I\vert = 1\)

根据 \(I_{i, j} = [i = j]\) 以及 定理1 易证。

3. 交换矩阵两行,行列式变号。

交换 \(i, j\) 等价于交换每个排列的 \(p_i, p_j\),这会使所有 \(\tau(p)\) 奇偶性改变,相当于整体乘了个 \(-1\)

4. 将矩阵某行乘上一个常数,行列式乘上相同常数。

不妨将第 \(r\) 行所有元素乘 \(k\)\(\prod_{i = 1}^n A_{i, p_i}\) 恰好包含一个第 \(r\) 行元素,把 \(k\) 提出来。

5. 若矩阵有相同的两行,则行列式为 \(0\)

交换两行会使行列式变号,但是矩阵没变,即 \(\vert A\vert = -\vert A\vert \implies \vert A\vert = 0\)

6. 若矩阵有两行存在倍数关系,则行列式为 \(0\)

\(k \vert A\vert = -k\vert A\vert \implies \vert A\vert = 0\)

7. 若两个矩阵至多有一行不等,将这不等的一行相加得到的新矩阵的行列式等于原行列式之和。

设不等的行编号为 \(c\),新矩阵 \(S\) 满足 \(S_i = A_i = B_i,\ S_c = A_c + B_c(i \ne c)\)

\(\prod_{i = 1}^nS_{i, p_i} = (A_{c, p_c} + B_{c, p_c})\prod_{i = 1}^n[i\ne c]A_{i, p_i} = \prod_{i = 1}^nA_{i, p_i} + \prod_{i = 1}^nB_{i, p_i}\)

8. 将矩阵的某行加上另一行的倍数,行列式不变。

设把 \(c\)\(k\) 倍加到 \(d\) 上,设新矩阵为 \(C\)

\(B_i = A_i, B_d = kA_c(i \ne c)\),根据定理 7可得 \(\vert A\vert + \vert B\vert = \vert C\vert\),根据定理6可得 \(\vert B\vert = 0\)

高斯消元

步骤略。

P4783 【模板】矩阵求逆

题意:求一个 \(n \times n\) 的矩阵 \(A\) 在模 \(10^9 + 7\) 意义下的逆矩阵。

\(A\) 进行线性变换相当于左乘一个矩阵,也就是说把 \(A\) 变换(消元)到单位矩阵 \(I\),相当于左乘 \(A^{-1}\)

有恒等式 \(A^{-1} \times A = I\),那么在 \(A\) 变换到 \(I\) 的同时 \(I\) 也做同样的变换,最后得到 \(A^{-1} \times I = A^{-1}\)

矩阵可逆当且仅当 \(\vert A\vert \ne 0\),即满秩。submission

P7112 【模板】行列式求值

题意:给定一个 \(n\) 阶行列式,求 \(\vert A\vert\)。结果对 \(p\) 取模,不保证 \(p\) 是素数。

\(A\) 消成上三角矩阵,最后答案就是主对角线之积。

加上某一行的倍数不改变答案,而交换两行会使符号改变,因此记录交换了多少次。

没有必要对一行乘某个常数的操作,否则还有额外记录乘了多少东西。

\(p\) 没有特殊性质,不能求逆元,因此采用类似「辗转相除法」对两行消元,时间复杂度 \(O(n^3\log p)\)

#include<bits/stdc++.h>
#define eb emplace_back
#define ep emplace
using namespace std;

using ll = long long;

int n, p, sgn; ll a[605][605];

int main() {
	cin.tie(0)->sync_with_stdio(0);
	cin >> n >> p;
	for(int i = 1; i <= n; ++ i) {
		for(int j = 1; j <= n; ++ j) {
			cin >> a[i][j];
			a[i][j] %= p;
		}
	}
	for(int k = 1; k <= n; ++ k) {
		for(int i = k; i <= n; ++ i) {
			if(a[i][k]) {
				if(i != k) {
					swap(a[i], a[k]), sgn ^= 1;
				}
				break;
			}
		}
		if(!a[k][k]) return cout << 0, 0;
		for(int i = k + 1; i <= n; ++ i) {
			while(a[i][k]) {
				if(a[i][k] < a[k][k]) {
					swap(a[i], a[k]), sgn ^= 1;
				} 
				ll q = a[i][k] / a[k][k];
				for(int j = k; j <= n; ++ j) {
					a[i][j] = (a[i][j] + p - q * a[k][j] % p) % p;
				}
			}
		}
	}
	ll tmp = 1;
	for(int i = 1; i <= n; ++ i) tmp = tmp * a[i][i] % p;
	cout << (sgn ? (p - tmp) % p : tmp);
	return 0;
}

矩阵树定理

无向图生成树个数

\(G\) 是一个有 \(n\) 个点的无向图,定义度数矩阵 \(D\) 为:

\[D_{ii} = \deg(i),\ D_{ ij} = 0,\ i\ne j \]

\(e(i, j)\) 表示点 \(i\) 与点 \(j\) 相连的边数,并定义邻接矩阵 \(A\) 为:

\[A_{ij} = A_{ji} = e(i, j),\ i \ne j \]

定义拉普拉斯矩阵:

\[L = D - A \]

记图 \(G\) 的所有生成树个数为 \(t\)

\[t(G) = \det L\begin{pmatrix}1, 2, \cdots, i - 1, i + 1, \cdots, n\\1, 2, \cdots, i - 1, i + 1, \cdots, n \end{pmatrix} \]

其中记号 \(L(G)\binom{1, 2, \cdots, i - 1, i + 1, \cdots, n}{1, 2, \cdots, i - 1, i + 1, \cdots, n}\) 表示矩阵 \(L\) 的第 \([1, i)(i, n]\) 行与 \([1, i)(i, n]\) 列构成的子矩阵。

无向图拉普拉斯矩阵所有 \(n - 1\) 阶主子式都相等。

有向图生成树个数

定义出度矩阵 \(D_{out}(i, i) = \deg^{out}(i), D_{out}(i, j \ne i) = 0\)

\(e(i, j)\) 表示 \(i\) 指向 \(j\) 的有向边数,定义邻接矩阵 \(A\)

\[A_{ij} = e(i, j), \ j \ne i \]

定义出度拉普拉斯矩阵 \(L_{out}\)

\[L_{out} = D_{out} - A \]

同理定义入度矩阵 \(D_{in}, L_{in}\)

记以 \(r\) 为根的所有内向生成树个数为 \(t^{root}(r)\),内向表示所有边全部指向父亲。

记以 \(r\) 为根的所有外向生成树个数为 \(t^{leaf}(r)\),外向表示所有边全部指向儿子。

\[\begin{aligned} t^{root}(r) = \det L_{out}\begin{pmatrix}1, 2, \cdots, k - 1, k + 1, \cdots, n\\1, 2, \cdots, k - 1, k + 1, \cdots, n\end{pmatrix}\\ \\ t^{leaf}(r) = \det L_{in}\begin{pmatrix}1, 2, \cdots, k - 1, k + 1, \cdots, n\\1, 2, \cdots, k - 1, k + 1, \cdots, n\end{pmatrix}\\ \end{aligned} \]

边权积的和

对于一条 \((u, v, w)\) 会对该方案贡献 \(w\) 的系数,这等价于拆成 \(w\)\((u, v)\),方案数乘 \(w\)

BEST定理

\(G\) 是有向欧拉图,那么 \(G\) 的不同欧拉回路总数:

\[ec(G) = t^{root}(k) \prod_{v \in V} (\deg_{out}(v) - 1)! \]

欧拉图任意节点为根的外向树数量相等,且所有节点出度和入度相等(这也说明 \(t^{root}(k) = t^{leaf}(k)\))。

注意:BEST定理只能在欧拉图上使用。

P5807 【模板】BEST 定理 | Which Dreamed It

题意:求从 \(1\) 开始的欧拉回路数量。

对于一条欧拉回路,保留除 \(1\) 外所有点路径中的最后一条出边,\(1\) 的出边全部删掉。

此时图中一定无环。

这样除了 \(1\) 每个点会被保留恰好一条出边,且整张图连通,形成一颗以 \(1\) 为根的内向树。

我们钦定一棵内向树,然后对于其他边任意定顺序,一定唯一对应一个欧拉回路。

充分性有了,考虑必要性,显然每一个欧拉回路都唯一对应一颗内向树和其中遍历出边的顺序。

因此总方案就是

\[t^{root}(1) \times d_1! \times \prod_{i \ne 1} (d_i - 1)! \]

由此可以引出BEST定理,统计整张图本质相同的欧拉回路个数(循环同构)。

\(1\) 会在一个欧拉回路会出现 \(d_1\) 次,每种方案都能旋转生成 \(d_1\) 中以 \(1\) 为起点的方案,因此每种方案被重复计算 \(d_1\) 次:

\[t^{root}(1) \prod (d_i - 1)! \]

submission

posted @ 2024-09-26 16:48  Lu_xZ  阅读(110)  评论(0)    收藏  举报