先膜拜 zxyoi
题意:求
n
≤
50
n\le 50
n≤50 个点
m
≤
50
m\le 50
m≤50 条边
前
k
≤
2
k\le 2
k≤2 个点的度数只能是 2 的带标号无向图个数
首先考虑
k
=
0
k=0
k=0 的情况
大力
d
p
dp
dp 容斥转移
f
[
n
]
[
m
]
=
(
(
n
2
)
m
)
−
∑
i
=
1
n
−
1
(
n
−
1
i
−
1
)
∑
j
=
1
m
f
[
i
]
[
j
]
∗
(
(
n
−
i
2
)
m
−
j
)
f[n][m]=\binom{\binom{n}{2}}{m}-\sum_{i=1}^{n-1}\binom{n-1}{i-1}\sum_{j=1}^mf[i][j]*\binom{\binom{n-i}{2}}{m-j}
f[n][m]=(m(2n))−i=1∑n−1(i−1n−1)j=1∑mf[i][j]∗(m−j(2n−i))
k = 1 k=1 k=1,考虑先把一个图填好,然后随便选一条边把这个点插进去
发现需要分放进去的点在不在三元环中讨论
不在的话就多了一个点一条边,
(
m
−
1
)
f
[
n
−
1
]
[
m
−
1
]
(m-1)f[n-1][m-1]
(m−1)f[n−1][m−1]
否则多了一个点两条边,
(
m
−
2
)
f
[
n
−
1
]
[
m
−
2
]
(m-2)f[n-1][m-2]
(m−2)f[n−1][m−2]
k
=
2
k=2
k=2
分两个点有没有捆绑讨论:
没有捆绑:
两个点都在 3 元环中,发现可以有公共边
两个的填发不冲突,
(
m
−
4
)
2
f
[
n
−
2
]
[
m
−
4
]
(m-4)^2f[n-2][m-4]
(m−4)2f[n−2][m−4]
一个点在 3 元环,一个点不在, 2 ∗ ( m − 3 ) ∗ ( m − 4 ) ∗ f [ n − 2 ] [ m − 3 ] 2*(m-3)*(m-4)*f[n-2][m-3] 2∗(m−3)∗(m−4)∗f[n−2][m−3]
两个点都不在:
需要分有没有形成 4 元环讨论,如果形成了就是
(
m
−
3
)
f
[
n
−
2
]
[
m
−
3
]
(m-3)f[n-2][m-3]
(m−3)f[n−2][m−3]
如果没有就是
(
m
−
2
)
∗
(
m
−
3
)
∗
f
[
n
−
2
]
[
m
−
2
]
(m-2)*(m-3)*f[n-2][m-2]
(m−2)∗(m−3)∗f[n−2][m−2]
两个点捆绑:
捆绑插到一条边中,发现需要分有没有形成 4 元环讨论
如果没有形成那么为
2
∗
(
m
−
2
)
∗
f
[
n
−
2
]
[
m
−
2
]
2*(m-2)*f[n-2][m-2]
2∗(m−2)∗f[n−2][m−2],注意两个点交换不同构
如果形成了就是
2
∗
(
m
−
3
)
∗
f
[
n
−
2
]
[
m
−
3
]
2*(m-3)*f[n-2][m-3]
2∗(m−3)∗f[n−2][m−3]
两个点连到同一个点上,交换同构, ( n − 2 ) ∗ f [ n − 2 ] [ m − 3 ] (n-2)*f[n-2][m-3] (n−2)∗f[n−2][m−3]
自己拍了一下没有交
#include<bits/stdc++.h>
#define cs const
using namespace std;
cs int N = 50, M = N*N;
cs int Mod = 1e9 + 7;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b;}
int mul(int a, int b){ return 1ll * a * b % Mod; }
void Add(int &a, int b){ a = add(a, b); }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
void Dec(int &a, int b){ a = dec(a, b); }
int C2(int n){ return n * (n-1) / 2; }
int n, m, k, c[M][M], f[N][N];
void prework(){
int up = C2(n); c[0][0] = 1;
for(int i = 1; i <= up; i++){
c[i][0] = 1; for(int j = 1; j <= i; j++) c[i][j] = add(c[i-1][j], c[i-1][j-1]);
}
for(int i = 1; i <= n; i++)
for(int j = i-1; j <= min(m,C2(i)); j++){
f[i][j] = c[C2(i)][j];
for(int p = 1; p < i; p++){
int coef = c[i - 1][p - 1];
for(int q = p-1; q <= min(j,C2(p)); q++)
Dec(f[i][j], mul(f[p][q], mul(coef, c[C2(i-p)][j-q])));
}
}
}
int F(int n, int m){ if(n<0||m<0) return 0; return f[n][m]; }
int main(){
cin >> n >> k >> m;
prework();
if(n == 1){ if(!m && !k) puts("1"); else puts("0"); }
if(n == 2){ if(m == 1 && !k) puts("1"); else puts("0"); }
if(k == 0) cout << f[n][m] << '\n';
if(k == 1) cout << add(mul(m-1,F(n-1,m-1)), mul(m-2,F(n-1,m-2))) << '\n';
if(k == 2){
int ans = 0;
Add(ans, mul(mul(m-4,m-4), F(n-2,m-4)));
Add(ans, mul(mul(m-3,m-4), mul(2,F(n-2,m-3))));
Add(ans, mul(mul(m-2,m-3), F(n-2,m-2)));
Add(ans, mul(m-3, F(n-2,m-3)));
Add(ans, mul(mul(2, m-2), F(n-2,m-2)));
Add(ans, mul(mul(2, m-3), F(n-2,m-3)));
Add(ans, mul(n-2, F(n-2,m-3)));
cout << ans << '\n';
} return 0;
}