Ksenia has her winter exams. Today she is learning combinatorics. Here’s one of the problems she needs to learn to solve.
How many distinct trees are there consisting of n vertices, each with the following properties:
the tree is marked, that is, the vertices of the tree are numbered from 1 to n;
each vertex of the tree is connected with at most three other vertices, and at the same moment the vertex with number 1 is connected with at most two other vertices;
the size of the tree’s maximum matching equals k.
Two trees are considered distinct if there are such two vertices u and v, that in one tree they are connected by an edge and in the other tree they are not.
Help Ksenia solve the problem for the given n and k. As the answer to the problem can be very huge you should output it modulo 1000000007 (109 + 7).
The first line contains two integers n, k (1 ≤ n, k ≤ 50).
Print a single integer — the answer to the problem modulo 1000000007 (109 + 7).
1 1
0
2 1
1
3 1
3
4 2
12
If you aren’t familiar with matchings, please, read the following link: http://en.wikipedia.org/wiki/Matching_(graph_theory).
简洁版题意:有n个节点的数,每个节点有不同的标号,求生成树匹配大小为k的方案数,其中除了根节点所有节点的度数不超过3,根节点1度数不超过2
考虑DP计数吧
dp[i][j][0/1] d p [ i ] [ j ] [ 0 / 1 ] 表示大小为i的子树,最大匹配是j,是否匹配当前节点的方案数
然后当i==n的时候和左右子树大小相同的情况需要特判掉
然后就是常规DP
#include
using namespace std;
#define yyf 1000000007
#define N 60
#define LL long long
LL dp[N][N][2];
LL C[N][N];
void update(LL &a,LL b){a=(a+b)%yyf;}
int main(){
LL n,k;scanf("%lld%lld",&n,&k);
if(k*2>n){printf("0");return 0;}
for(LL i=0;i<=n;i++)C[i][0]=1;
for(LL i=1;i<=n;i++)
for(LL j=1;j<=i;j++)C[i][j]=(C[i-1][j-1]+C[i-1][j])%yyf;
dp[1][0][0]=dp[0][0][1]=1;
for(LL siz=2;siz<=n;siz++)
for(LL mac=1;mac<=k;mac++){
//不匹配当前节点
for(LL ls=0,rs=siz-1;ls<=rs;ls++,rs--){
for(LL lm=0,rm=mac;lm<=mac;lm++,rm--){
if(lm*2>ls||rm*2>rs)continue;
LL tmp=(ls==rs?C[siz-2][ls-1]:C[siz-1][ls])*(siz==n?1:siz)%yyf;//特判掉左边大小等于右边
update(dp[siz][mac][0],dp[ls][lm][1]*dp[rs][rm][1]%yyf*tmp%yyf);
}
}
//匹配当前节点
for(LL ls=0,rs=siz-1;ls<=rs;ls++,rs--){
for(LL lm=0,rm=mac-1;lmif(lm*2>ls||rm*2>rs)continue;
LL tmp=(ls==rs?C[siz-2][ls-1]:C[siz-1][ls])*(siz==n?1:siz)%yyf;
update(dp[siz][mac][1],dp[ls][lm][1]*dp[rs][rm][0]%yyf*tmp%yyf);
update(dp[siz][mac][1],dp[ls][lm][0]*dp[rs][rm][1]%yyf*tmp%yyf);
update(dp[siz][mac][1],dp[ls][lm][0]*dp[rs][rm][0]%yyf*tmp%yyf);
}
}
}
printf("%lld",(dp[n][k][0]+dp[n][k][1])%yyf);
return 0;
}