矩阵树定理
行列式
线性代数基础知识,消成上三角矩阵拿出对角线元素乘积即可.
矩阵树定理
无向图
1. 对于每条边 $\mathrm{(x,y,z)}$ 给 $\mathrm{(x,x)}$ 与 $\mathrm{(y,y)}$ 加上 $\mathrm{z}$.
2. 对于每条边 $\mathrm{(x,y,z)}$ 给 $\mathrm{(x,y),(y,x)}$ 分别加上 $\mathrm{z}$.
设第一个矩阵为 $\mathrm{A}$, 第二个为 $\mathrm{B}$, 删去任意一行列求 $\mathrm{A-B}$ 行列式即可.
外向树(根指向叶子)
1. 对于每条边 $\mathrm{(x,y,z)}$ 给 $\mathrm{(y,y)}$ 加上 $\mathrm{z}$.
2. 对于每条边 $\mathrm{(x,y,z)}$ 给 $\mathrm{(x,y)}$ 加上 $\mathrm{z}$.
用第一个矩阵减去第二个矩阵求行列式即可,注意这里要删根所在的行列.
内向树(叶子指向根)
和外向树唯一不同就是 $\mathrm{1}$ 那里给 $\mathrm{(x,x)}$ 加上.
模板
这里进行消法的时候用的辗转相除,多一个 $\mathrm{log n}$ 但对模数无要求.
#include <bits/stdc++.h>
#define N 609
#define ll long long
#define pb push_back
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
const int mod = (int)1e9 + 7;
int ADD(int x, int y) {
return (ll)(x + y) % mod;
}
int DEC(int x, int y) {
return (ll)(x - y + mod) % mod;
}
int n, m, ty, a[N][N];
int DET() {
-- n;
int de = 1, fin = 1;
for(int i = 1; i <= n ; ++ i) {
for(int j = i + 1; j <= n ; ++ j) {
if(a[j][i]) {
swap(a[j], a[i]);
de *= -1;
while(a[j][i]) {
// a[i] 有值, a[j] 不一定.
int t = a[j][i] / a[i][i];
for(int k = i; k <= n ; ++ k) {
a[j][k] = DEC(a[j][k], (ll)t * a[i][k] % mod);
}
if(a[j][i]) swap(a[i], a[j]), de *= -1;
}
}
}
fin = (ll)fin * a[i][i] % mod;
}
return (ll)(fin * de + mod) % mod;
}
int main() {
// setIO("input");
scanf("%d%d%d", &n, &m, &ty);
for(int i = 1; i <= m ; ++ i) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
-- x, -- y;
if(ty == 0) {
a[x][x] = ADD(a[x][x], z);
a[y][y] = ADD(a[y][y], z);
a[x][y] = DEC(a[x][y], z);
a[y][x] = DEC(a[y][x], z);
}
else {
// x - y
a[y][y] = ADD(a[y][y], z);
a[x][y] = DEC(a[x][y], z);
}
}
printf("%d\n", DET());
return 0;
}

浙公网安备 33010602011771号