题意:
给出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() {
LD ans = 1.0;
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]);
ans = -ans;
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];
}
}
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;
}