题意
求 n n n个点,不超过 k k k条割边的有标号图个数。 1 ≤ n ≤ 50 , 0 ≤ k ≤ 50 1\le n\le50,0\le k\le50 1≤n≤50,0≤k≤50
题解
调得怀疑人生了,总算A了。。。
设 n n n个点的图个数为 e n e_n en, n n n个点连通图个数为 l n l_n ln, n n n个点强连通图个数为 g n g_n gn, n n n个点 k k k条割边的连通图个数为 f n , k f_{n,k} fn,k,则答案可以由 f f f数组求出。
显然有
e
n
=
2
n
(
n
−
1
)
2
l
n
=
e
n
−
∑
i
=
1
n
−
1
(
n
−
1
i
−
1
)
e
n
−
i
l
i
e_n=2^{\frac{n(n-1)}2}\\ l_n=e_n-\sum_{i=1}^{n-1}{n-1\choose i-1}e_{n-i}l_i
en=22n(n−1)ln=en−i=1∑n−1(i−1n−1)en−ili
求
g
n
g_n
gn需要一个辅助数组
G
k
,
n
G_{k,n}
Gk,n,代表有
k
k
k个点,把另外
n
n
n个点划分成一些连通块,每个连通块向这
k
k
k个点连边的方案数,
则
G
k
,
n
=
∑
i
=
1
n
(
n
−
1
i
−
1
)
l
i
×
i
k
×
G
k
,
n
−
i
g
n
=
l
n
−
∑
i
=
1
n
−
1
(
n
−
1
i
−
1
)
g
i
G
i
,
n
−
i
G_{k,n}=\sum_{i=1}^n{n-1\choose i-1}l_i\times ik\times G_{k,n-i}\\ g_n=l_n-\sum_{i=1}^{n-1}{n-1\choose i-1}g_iG_{i,n-i}
Gk,n=i=1∑n(i−1n−1)li×ik×Gk,n−ign=ln−i=1∑n−1(i−1n−1)giGi,n−i
求
f
n
,
k
f_{n,k}
fn,k需要一个辅助数组
F
k
,
j
,
i
F_{k,j,i}
Fk,j,i,代表有
k
+
i
k+i
k+i个点,可以在
i
i
i个点之间连边或者把它们和剩下
k
k
k个点连边,有
j
j
j条割边的方案数,
则
f
i
,
j
=
∑
k
=
1
i
−
1
(
i
−
1
k
−
1
)
g
k
F
k
,
j
,
i
−
k
F
k
,
j
,
i
=
∑
I
=
0
i
∑
J
=
0
j
−
1
(
i
−
1
I
−
1
)
f
I
,
J
×
k
I
×
F
k
,
j
−
J
−
i
,
i
−
I
f_{i,j}=\sum_{k=1}^{i-1}{i-1\choose k-1}g_kF_{k,j,i-k}\\ F_{k,j,i}=\sum_{I=0}^i\sum_{J=0}^{j-1}{i-1\choose I-1}f_{I,J}\times kI\times F_{k,j-J-i,i-I}
fi,j=k=1∑i−1(k−1i−1)gkFk,j,i−kFk,j,i=I=0∑iJ=0∑j−1(I−1i−1)fI,J×kI×Fk,j−J−i,i−I
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define IN inline
#define R register int
const int N=55;
const ll p=1000000007;
int n,k;
ll e[N],c[N][N],l[N],g[N],G[N][N],f[N][N],F[N][N][N],ans[N][N],S;
IN ll add(ll a,ll b){return a+b<p?a+b:a+b-p;}
IN ll sub(ll a,ll b){return a-b<0?a-b+p:a-b;}
IN ll mul(ll a,ll b){return a*b%p;}
IN ll expo(ll a,int b){
static ll c;c=1;
while(b){
if(b&1)c=c*a%p;
b>>=1; a=a*a%p;
}
return c;
}
int main(){
scanf("%d%d",&n,&k);
for(R i=1;i<=n;i++)e[i]=expo(2,(i*(i-1))>>1);
for(R i=0;i<=n;i++)c[i][0]=1;
for(R i=1;i<=n;i++)for(R j=1;j<=i;j++)c[i][j]=add(c[i-1][j],c[i-1][j-1]);
for(R i=1;i<=n;i++){
l[i]=e[i];
for(R j=1;j<i;j++)l[i]=sub(l[i],mul(mul(c[i-1][j-1],e[i-j]),l[j]));
}
for(R k=1;k<=n;k++)G[k][0]=1;
for(R k=1;k<=n;k++)for(R i=1;i<=n-k;i++)for(R j=1;j<=i;j++)
G[k][i]=add(G[k][i],mul(mul(c[i-1][j-1],j*k),mul(l[j],G[k][i-j])));
g[0]=1;
for(R i=1;i<=n;i++){
g[i]=l[i];
for(R j=1;j<i;j++)g[i]=sub(g[i],mul(mul(c[i-1][j-1],G[j][i-j]),g[j]));
}
for(R i=1;i<=n;i++)F[i][0][0]=1;
for(R i=1;i<=n;i++){
f[i][0]=g[i];
for(R j=1;j<i;j++)for(R k=1;k<i;k++)
f[i][j]=add(f[i][j],mul(mul(c[i-1][k-1],g[k]),F[k][j][i-k]));
for(R k=1;k<=n-i;k++)for(R j=0;j<i+k;j++)
for(R I=1;I<=i;I++)for(R J=0;J<j;J++)
F[k][j][i]=add(F[k][j][i],mul(mul( c[i-1][I-1],mul(f[I][J],k*I) ),F[k][j-J-1][i-I]));
}
ans[0][0]=1;
for(R i=1;i<=n;i++)for(R j=0;j<=i;j++)
for(R I=1;I<=i;I++)for(R J=0;J<=j;J++)ans[i][j]=add(ans[i][j],mul(c[i-1][I-1],mul(f[I][J],ans[i-I][j-J])));
for(R i=0;i<=k;i++)S=add(S,ans[n][i]);
printf("%lld",S);
return 0;
}