bzoj 5297 [Cqoi2018]社交网络 高斯消元+Matrix-Tree定理

题面

题目传送门

解法

有向图Matrix-Tree定理的裸题吧……

\((i,j)\)有边,那么\(a_{i,j}=-1\)\(a_{i,i}=d_i\)\(d_i\)为点\(i\)的出度

因为以1为根,所以只要求出\(2-n\)的行列式即可

md高斯消元写错一个东西照样90……数据是真的弱

时间复杂度:\(O(n^3)\)

代码

#include <bits/stdc++.h>
#define Mod 10007
#define N 300
using namespace std;
template <typename node> void read(node &x) {
    x = 0; int f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
    while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;
}
int a[N][N];
int Pow(int x, int y) {
    int ret = 1;
    while (y) {
        if (y & 1) ret = 1ll * ret * x % Mod;
        y >>= 1, x = 1ll * x * x % Mod;
    }
    return ret;
}
int solve(int n) {
    int ans = 1;
    for (int i = 2; i <= n; i++) {
        if (!a[i][i])
            for (int j = i + 1; j <= n; j++)
                if (a[j][i]) {                  
                    for (int k = 2; k <= n; k++) swap(a[j][k], a[i][k]);
                    ans = -ans; break;
                }
        int x = Pow(a[i][i], Mod - 2);
        for (int j = i + 1; j <= n; j++)
            if (a[j][i]) {
                int t = 1ll * a[j][i] * x % Mod;
                for (int k = 2; k <= n; k++) a[j][k] = (a[j][k] - t * a[i][k] % Mod + Mod) % Mod;
            }
    }
    for (int i = 2; i <= n; i++) ans = (ans * a[i][i]) % Mod;
    return (ans + Mod) % Mod;
}
int main() {
    int n, m; read(n), read(m);
    for (int i = 1; i <= m; i++) {
        int x, y; read(x), read(y);
        a[x][y] = (a[x][y] - 1 + Mod) % Mod, a[x][x]++;
    }
    cout << solve(n) << "\n";
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/copperoxide/p/9478382.html