先膜拜 zxyoi
题意:求
个点
条边
前
个点的度数只能是 2 的带标号无向图个数
首先考虑
的情况
大力
容斥转移
,考虑先把一个图填好,然后随便选一条边把这个点插进去
发现需要分放进去的点在不在三元环中讨论
不在的话就多了一个点一条边,
否则多了一个点两条边,
分两个点有没有捆绑讨论:
没有捆绑:
两个点都在 3 元环中,发现可以有公共边
两个的填发不冲突,
一个点在 3 元环,一个点不在,
两个点都不在:
需要分有没有形成 4 元环讨论,如果形成了就是
如果没有就是
两个点捆绑:
捆绑插到一条边中,发现需要分有没有形成 4 元环讨论
如果没有形成那么为
,注意两个点交换不同构
如果形成了就是
两个点连到同一个点上,交换同构,
扫描二维码关注公众号,回复:
8675840 查看本文章
自己拍了一下没有交
#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;
}