矩阵树定理


行列式

线性代数基础知识,消成上三角矩阵拿出对角线元素乘积即可.  

矩阵树定理

无向图

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  
#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; 
}