行列式
线性代数基础知识,消成上三角矩阵拿出对角线元素乘积即可.
矩阵树定理
无向图
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; }