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

posted @ 2018-08-14 22:26  谜のNOIP  阅读(102)  评论(0编辑  收藏  举报