太厉害了!!!!!!
首先竞赛图有个性质,若存在环则一定存在三元环。
先把 DAG 的情况(一条链)特判了。然后缩点。发现非链底的部分不能存在大小 \(> 1\) 的 SCC。所以枚举非链底的部分有多少点,转化为 SCC 的情况。
发现对于任意点(设为 \(1\) 号点),它的前驱连成一条链,后继也是一条链。
如果前驱有环那么和 \(1\) 可以形成子图。如果后继最后有一个 SCC,考虑拿出前驱的链顶 \(y\)。显然这个 SCC 的点不能全部连向 \(y\)。所以这个 SCC 能分成两个非空集合 \(S_1, S_2\),满足一个连向 \(y\),一个被 \(y\) 连。发现 \(S_1\) 不能存在到 \(S_2\) 的边。所以这不是一个 SCC。
设前驱的链为 \(A_{1 \sim a}\),后继的链为 \(B_{1 \sim b}\)。
首先因为这是一个 SCC 所以一定有 \(B_b \to A_1\) 的边。
然后我们发现对于前驱的点,它一定是有一段连向后继的前缀,剩下的后缀是连向这个点。
设前驱第 \(i\) 个点连向后继的是 \([1, p_i]\)。又发现 \(p\) 单调不降。
然后就可以转化为对于 \(p\) 计数。入度判一下即可。
时间复杂度 \(O(n^4)\)。
code
// Problem: F - Forbidden Tournament
// Contest: AtCoder - AtCoder Grand Contest 046
// URL: https://atcoder.jp/contests/agc046/tasks/agc046_f
// Memory Limit: 1024 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))
using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;
const int maxn = 210;
ll n, m, mod, fac[maxn], C[maxn][maxn], f[maxn][maxn];
inline ll calc(ll n, ll m) {
ll ans = 0;
for (int a = 1; a < n - 1; ++a) {
int b = n - 1 - a;
mems(f, 0);
if (a > m || b > m) {
continue;
}
for (int i = 0; i < b; ++i) {
if (b - i <= m && (!i || a + i <= m)) {
f[1][i] = 1;
}
}
for (int i = 2; i <= a; ++i) {
ll s = 0;
for (int j = 0; j <= b; ++j) {
s = (s + f[i - 1][j]) % mod;
if (i - 1 + b - j <= m && (!j || j + a - i + 1 <= m)) {
f[i][j] = s;
}
}
}
for (int i = 0; i <= b; ++i) {
ans = (ans + fac[n - 1] * f[a][i]) % mod;
}
}
return ans;
}
void solve() {
scanf("%lld%lld%lld", &n, &m, &mod);
fac[0] = 1;
for (int i = 1; i <= n; ++i) {
fac[i] = fac[i - 1] * i % mod;
}
for (int i = 0; i <= n; ++i) {
C[i][0] = C[i][i] = 1;
for (int j = 1; j < i; ++j) {
C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;
}
}
ll ans = (m == n - 1 ? fac[n] : 0);
for (int i = 0; i <= n - 3 && i < m; ++i) {
ans = (ans + C[n][i] * fac[i] % mod * calc(n - i, m - i)) % mod;
}
printf("%lld\n", ans);
}
int main() {
int T = 1;
// scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}