矩阵树定理——2025.5.12 鲜花

矩阵树定理

モニタリング
ねえあたし知ってるよ
きみがひとり“XX”してるの
知ってるよ
ビクンビクン震えてさ
声もダダ漏れなんだわ
正直に言っちゃえよ
バレてるんだし言っちゃえよ
効いてんの?
普通普通 恥ずかしい?
みんな隠しているだけ
ねえあたし知ってるよ
きみがひとり“涙”してるの
知ってるよ
グスングスン凹んでさ
弱音ヒトカラ in the night
朝が来るまで一緒コース
もっと泣いたって
何度だって受け止めてあげる
もう我慢しないでいっぱい出してね
Mwah お願い きみが欲しいの
慰めさせてシェイクシェイク
愛の才能で
泣いてくれなきゃ涸れてしまう
濡れていたい
ねえいいでしょう?
舐め取って 飲み干したいんだってば
Mwah お願い きみが欲しいの
頼り散らしてシックラブ
なんて最高ね
分けてくれなきゃ
君の“痛い”感じていたい
ねえいいでしょう?
吸い取って 救いたいんだってば
見たいの きみの中
見たいの
ねえあたし知ってるよ
きみがひとり悔しがってんの
知ってるよ
ズキュンズキュン高まるじゃん
きみを推すことをやめない
ねえあたし知ってるよ
きみはできる子 知ってるよ
つらい時は弱いくらいで丁度いい
あたしそれでも好きだよ
Mwah お願い きみが欲しいの
名前を呼んでよ
いつだって会いに参上
きみはひとりだ
だから歌う「ひとりじゃない」
もういいでしょう
ソロプレイは
お仕舞いなんだってば
きみが病めるときも
あたし側にいるわ
いつも見守っているわ
そうよ 怖くないのよ
Mwah お願い きみが欲しいの
慰めさせてシェイクシェイク
愛の才能で
泣いてくれなきゃ涸れてしまう
濡れていたい
ねえいいでしょう?
舐め取って 飲み干したいんだってば
Mwah お願い きみが欲しいの
頼り散らしてシックラブ
なんて最高ね
分けてくれなきゃ
君の“痛い”感じていたい
覗いていたい
吸い取って 救いたいんだってば
ねえあたし知ってるよ
きみがひとり“涙”してるの
知ってるよ
グスングスン凹んでさ
弱音ヒトカラ in the night
朝が来るまで一緒コース
もっと泣いたって
何度だって受け止めてあげる
もう我慢しないで出してってば
さあ

证明会不了一点,这里直接给结论。

首先会一下矩阵求行列式。

有定义式:

\[\det(A) = \sum_P (-1)^{\mu(P)}\prod_{i = 1} ^ n A_{i, p_i} \]

其中 \(\mu\) 表示逆元数量。

然后我们知道几个比较显然的性质,就可以快速算行列式了。

首先上三角或下三角矩阵的行列式为对角线之积。

然后交换两行行列式取反、一行加上另一行的倍数行列式不变。

于是就可以直接暴力高消了。

高消的时候有个八百年不用一次的技巧,就是当模数不是质数时可以用类似辗转相除来消掉一行,复杂度不变。

然后矩阵数定理有一下几点:

  1. 无向图:

    我们定义 Kirchhoff 矩阵为 \(\text{度数矩阵} - \text{邻接矩阵}\),则生成树个数等于其去掉任意第 \(k\)\(k\) 列后的行列式的值。

    其实我们去掉第 \(k\) 行相当于是用 \(k\) 做根,但是无向图生成树个数与根无关。

  2. 有向图:

    这个分外向树和内向树。

    外向树就是吧度数矩阵设成入度,内向树就是出度。

    这里不同的根就不一样了。

  3. Best 定理:

    欧拉图的欧拉回路数量是:

    不钦定起点:\(t^{root}(G, k) \prod_u (deg_u - 1)!\)\(t^{root}(G, k)\) 表示 \(G\)\(k\) 为根的内向树生成树个数,其中 \(k\) 可以任取。

    欧拉图每个点的出入度是一样的,所以事实上内向树或外向树没区别。

    钦定起点要乘上起点 \(k\) 的度数。

带权就不是很有意思了,当成多条边即可,求的是生成树的边权积。

放个模板题的代码吧:

Code
/* Local File
in_out/in.in
in_out/out.out
*/
#include <bits/stdc++.h>
using namespace std;
using llt = long long;
using ull = unsigned long long;
using llf = long double;
#define endl '\n'

const int N = 303, MOD = 1e9 + 7;
int n, m, _t, gp[N][N];

int Det(int a[N][N], int l){
	int v = 1;
	for(int i = 2; i <= l; ++i){
		int t = 0;
		for(int j = i; j <= l; ++j) if(a[j][i]) t = j;
		if(!t) return 0;
		if(i != t) swap(a[i], a[t]), v = -v;
		for(int j = i + 1; j <= l; ++j) while(a[j][i]){
			if(abs(a[j][i]) < abs(a[i][i])) swap(a[j], a[i]), v = -v;
			int t = a[j][i] / a[i][i];
			for(int k = i; k <= l; ++k) a[j][k] = (a[j][k] - 1ll * a[i][k] * t) % MOD;
		}
	}
	for(int i = 2; i <= l; ++i) v = 1ll * v * a[i][i] % MOD;
	return v;
}

int main(){
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	cin >> n >> m >> _t;
	if(_t) for(int i = 1 ; i <= m; ++i){
		int u, v, w; cin >> u >> v >> w;
		gp[u][v] = (gp[u][v] - w) % MOD, gp[v][v] = (gp[v][v] + w) % MOD;
	}
	else for(int i = 1 ; i <= m; ++i){
		int u, v, w; cin >> u >> v >> w;
		gp[u][v] = (gp[u][v] - w) % MOD, gp[v][u] = (gp[v][u] - w) % MOD;
		gp[u][u] = (gp[u][u] + w) % MOD, gp[v][v] = (gp[v][v] + w) % MOD;
	}
	cout << (Det(gp, n) + MOD) % MOD;
}
P

posted @ 2025-05-12 07:00  xrlong  阅读(41)  评论(1)    收藏  举报

Loading