题目
有n个点,m个桥的有向图有多少?
思路
比较烦的一道题
代码
#include <bits/stdc++.h>
#define ll long long
#define mk make_pair
using namespace std;
const int N = 105;
const int mod = 1e9 + 7;
int n, B;
int C[N][N], P[N][N], P2[N * N], F[N];
int f[N][N], g[N][N][N];
int main() {
freopen("bridge.in", "r", stdin);
freopen("bridge.out", "w", stdout);
for (int i = 0; i < N; i++) C[i][0] = 1;
for (int i = 1; i < N; i++)
for (int j = 1; j <= i; j++)
C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;
for (int i = 1; i < N; i++) {
P[i][0] = 1;
for (int j = 1; j < N; j++)
P[i][j] = (ll)P[i][j - 1] * i % mod;
}
P2[0] = 1;
for (int i = 1; i < N * N; i++)
P2[i] = (ll)P2[i - 1] * 2 % mod;
for (int i = 1; i < N; i++) {
F[i] = P2[i * (i - 1) / 2];
for (int j = 1; j < i; j++) {
F[i] -= (ll)F[j] * C[i - 1][j - 1] % mod * P2[(i - j) * (i - j - 1) / 2] % mod;
F[i] += mod;
F[i] %= mod;
}
}
scanf("%d %d", &n, &B);
for (int i = 1; i <= n; i++) {
f[i][0] = F[i];
for (int j = 1; j < i; j++) {
for (int k = 0; k < i - j; k++) {
for (int l = 1; l <= i - j; l++) {
f[i][0] -= (ll)f[j][0] * C[i - 1][j - 1] % mod * g[i - j][k][l] % mod * P[j][l] % mod;
f[i][0] += mod;
f[i][0] %= mod;
}
}
}// cout << f[i][0] << "/" << F[i] << endl;
//
for (int j = 1; j < i; j++) {
for (int k = 0; k < i - j; k++) {
for (int l = 1; l <= i - j; l++) {
f[i][k + l] += (ll)f[j][0] * C[i - 1][j - 1] % mod * g[i - j][k][l] % mod * P[j][l] % mod;
f[i][k + l] %= mod;
}
}
}
//
for (int j = 0; j < i; j++) g[i][j][1] = (ll)f[i][j] * i % mod;
for (int j = 1; j < i; j++) {
for (int k = 0; k < j; k++) {
for (int kk = 0; kk < i - j; kk++) {
for (int l = 1; l <= i - j; l++) {
g[i][k + kk][l + 1] += (ll)g[j][k][1] * C[i - 1][j - 1] % mod * g[i - j][kk][l] % mod;
g[i][k + kk][l + 1] %= mod;
}
}
}
}
}//cout << f[3][2] << endl;
//for (int i = 0; i < 3; i++)
//for (int j = 1; j <= 3; j++)
//cout << "3" << " " << i << " " << j << " " << g[3][i][j] << endl;
ll ans = 0;
B = min(B, n - 1);
for (int i = 0; i <= B; i++)
(ans += f[n][i]) %= mod;
cout << ans << endl;
}