求
n
n
n 个点
m
m
m 条边,前
k
k
k 个点的度数均为
2
2
2 的无向连通图个数,无重边自环。
1
≤
n
,
m
≤
50
,
0
≤
k
≤
2
1\le n,m \le 50,0\le k\le 2
1≤n,m≤50,0≤k≤2
无脑讨论就行了。
#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define ll long long
namespace io {
const int SIZE = (1 << 21) + 1;
char ibuf[SIZE], *iS, *iT, obuf[SIZE], *oS = obuf, *oT = oS + SIZE - 1, c, qu[55]; int f, qr;
// getchar
#define gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, SIZE, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
// print the remaining part
inline void flush () {
fwrite (obuf, 1, oS - obuf, stdout);
oS = obuf;
}
// putchar
inline void putc (char x) {
*oS ++ = x;
if (oS == oT) flush ();
}
// input a signed integer
template <class I>
inline void gi (I &x) {
for (f = 1, c = gc(); c < '0' || c > '9'; c = gc()) if (c == '-') f = -1;
for (x = 0; c <= '9' && c >= '0'; c = gc()) x = x * 10 + (c & 15); x *= f;
}
// print a signed integer
template <class I>
inline void print (I &x) {
if (!x) putc ('0'); if (x < 0) putc ('-'), x = -x;
while (x) qu[++ qr] = x % 10 + '0', x /= 10;
while (qr) putc (qu[qr --]);
}
//no need to call flush at the end manually!
struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
}
using io :: gi;
using io :: putc;
using io :: print;
const int p = 1e9+7;
int n,m,k;
int fac[3100],inv[3100];
inline int calc(int a,int b){return (a+b)%p;}
inline int del(int a,int b){return (a-b+p)%p;}
inline int mul(int a,int b){return 1ll*a*b%p;}
inline int ksm(int a,int x){int now = 1;for(;x;x>>=1,a=1ll*a*a%p) if(x&1) now = 1ll*now*a%p;return now;}
inline int sqr(int x){return 1ll*x*x%p;}
inline int C(int x,int y){return (y<0||y>x)?0:mul(fac[x],mul(inv[y],inv[x-y]));}
const int inv2 = ksm(2,p-2);
const int inv3 = ksm(3,p-2);
namespace pt1{
int f[100][100],g[100];
void work(){
rep(i,1,n) g[i] = mul(i,mul(i-1,inv2));
rep(i,1,n) rep(j,i-1,k) {
f[i][j] = C(g[i],j);
rep(t,1,i-1) rep(sz,t-1,j) //t为1所在联通快大小,sz为边数
f[i][j] = del(f[i][j],mul(mul(f[t][sz],C(g[i-t],j-sz)),C(i-1,t-1)));
}
}
}using namespace pt1;
namespace pt2{
void work(){
int ans = mul(f[n-1][k-2],C(n-1,2));
int tmp = 0;
rep(i,1,n-2) rep(j,0,k-2)
tmp = calc(tmp,mul( mul( i , n-1-i ) , mul( f[i][j] , mul( f[n-1-i][k-2-j] , C(n-1,i) ) )));
ans = calc(ans,mul(tmp,inv2));
printf("%d\n",ans);
}
}using namespace pt2;
namespace pt3{
void work(){
int ans = mul(f[n-2][k-4],mul(C(n-2,2),C(n-2,2)));
ans = calc(ans,mul(mul(f[n-2][k-3],C(n-2,2) ) ,2 ));
ans = calc(ans,mul(mul(f[n-2][k-3],C(n-2,1)) ,1 ));
int fuck1 = 0 , fuck2 = 0;
rep(i,1,n-3) rep(j,0,k-4){
int tmp = mul(f[i][j],mul(f[n-2-i][k-4-j],C(n-2,i)));
fuck1 = calc(fuck1,mul( mul(sqr(i) , sqr(n-2-i)) , tmp ));
fuck2 = calc(fuck2,mul( mul(2,tmp) ,mul( mul(i,n-2-i) , C(i,2) ) ) );
}
fuck1 = mul(fuck1,inv2);
ans = calc(ans,calc(fuck1,fuck2)); fuck1 = 0;
rep(i,1,n-3) rep(j,0,k-3){
fuck1 = calc(fuck1,mul( f[i][j] , mul( f[n-2-i][k-3-j] , mul( C(n-2,i) , mul( i , n-2-i ) ) ) ) );
}
ans = calc(ans,fuck1);
fuck1 = 0;
rep(i,1,n-4){
rep(j,1,n-4) if(i+j <= n-3){
int t = n - 2 - i - j;
rep(a,0,k-4) if(f[i][a]){
rep(b,0,k-4-a) if(f[j][b]){
int c = k-4-a-b;
if(!f[t][c]) continue;
fuck2 = mul( f[i][a] , mul( f[j][b] , f[t][c] ) );
fuck2 = mul( fuck2 , mul( C( n-2 , i ) , C( n-2-i , j ) ) );
fuck1 = calc( fuck1 , mul( fuck2 , mul( sqr(i) , mul( j , mul( 1 , t ) ) ) ) );
}
}
}
}
mul(fuck1,32);
printf("%d\n",calc(ans,fuck1));
}
}using namespace pt3;
int main(){
freopen("road.in","r",stdin);
freopen("road.out","w",stdout);
gi(n); gi(m); gi(k);
fac[0] = inv[0] = 1;
rep(i,1,3000) fac[i] = 1ll*fac[i-1]*i%p,inv[i] = ksm(fac[i],p-2);
if(m == 0) pt1::work(),printf("%d\n",pt1::f[n][k]);
else if(m == 1) pt1::work(),pt2::work();
else pt1::work(),pt3::work();
return 0;
}