【LOJ】#2532. 「CQOI2018」社交网络

时间:2023-03-08 15:36:20

题解

基尔霍夫矩阵,外向树是入度矩阵-邻接矩阵

必须删掉第一行第一列然后再求行列式

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int, int>
#define pdi pair<db, int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 1000005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template <class T>
void read(T &res) {
res = 0;
char c = getchar();
T f = 1;
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template <class T>
void out(T x) {
if (x < 0) {
x = -x;
putchar('-');
}
if (x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
const int MOD = 10007;
int g[255][255], N, M;
int inc(int a, int b) { return a + b >= MOD ? a + b - MOD : a + b; }
int mul(int a, int b) { return 1LL * a * b % MOD; }
int fpow(int x, int c) {
int res = 1, t = x;
while (c) {
if (c & 1) res = mul(res, t);
t = mul(t, t);
c >>= 1;
}
return res;
}
int determinant() {
int res = 1;
for (int i = 2; i <= N; ++i) {
int l;
for (l = i; l <= N; ++l) {
if (g[l][i]) break;
}
if (l != i) {
res = -res;
for (int j = i; j <= N; ++j) swap(g[i][j], g[l][j]);
}
int inv = fpow(g[i][i], MOD - 2);
for (int j = i + 1; j <= N; ++j) {
int t = mul(g[j][i], inv);
if (t) {
for (int k = i; k <= N; ++k) {
g[j][k] = inc(g[j][k], MOD - mul(t, g[i][k]));
}
}
}
}
res = (res + MOD) % MOD;
for (int i = 2; i <= N; ++i) {
res = mul(res, g[i][i]);
}
return res;
}
void Solve() {
read(N);
read(M);
int u, v;
for (int i = 1; i <= M; ++i) {
read(u);
read(v);
++g[u][u];
--g[v][u];
}
for (int i = 1; i <= N; ++i) {
for (int j = 1; j <= N; ++j) {
g[i][j] = inc(g[i][j], MOD);
}
}
out(determinant());
enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in", "r", stdin);
#endif
Solve();
return 0;
}