您的位置:首页 > 其它

【SPOJ-HIGH】Highways【高斯消元】【Matrix Tree定理】【行列式】

2016-02-18 17:42 519 查看
题意:

给出n个点,m条边,求生成树个数。

n <= 12,直接Matrix Tree定理,用度数矩阵减去邻接矩阵,然后求任意n - 1阶的行列式值即可。

注意开LL。

(又写了一发高斯消元)

#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

typedef long long LL;
typedef long double LD;

const int maxn = 15;
const double eps = 1e-3;

int n, m, du[maxn];
double a[maxn][maxn];

inline int iread() {
	int f = 1, x = 0; char ch = getchar();
	for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return f * x;
}

LL gauss() {
	for(int i = 1; i <= n; i++) {
		if(fabs(a[i][i] - 0.0) < eps) for(int j = i + 1; j <= n; j++) if(fabs(a[j][i] - 0.0) > eps) {
			for(int k = 1; k <= n; k++) swap(a[i][k], a[j][k]);
			break;
		}
		for(int j = i + 1; j <= n; j++) if(fabs(a[j][i] - 0.0) > eps) {
			double t = a[j][i] / a[i][i];
			for(int k = i; k <= n; k++) a[j][k] -= t * a[i][k];
		}
	}
	LD ans = 1.0;
	for(int i = 1; i <= n; i++) ans *= a[i][i];
	return (LL)(ans + eps);
}		

int main() {
	int T = iread();
	while(T--) {
		n = iread(); m = iread();
		for(int i = 1; i <= n; i++) {
			du[i] = 0;
			for(int j = 1; j <= n; j++) a[i][j] = 0.0;
		}

		for(int i = 1; i <= m; i++) {
			int x = iread(), y = iread();
			du[x]++; du[y]++;
			a[x][y] = a[y][x] = 1.0;
		}

		for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) a[i][j] = (double)(i == j) * du[i] - a[i][j];
		n--;
		LL ans = gauss();

		printf("%lld\n", ans);
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: