版权声明:http://blog.csdn.net/Mitsuha_。 https://blog.csdn.net/Mitsuha_/article/details/82226505
思路:树形DP。
表示以 为根的子树内,放了 人的方案数。
对于以 为根节点的子树,有3种状态。
0:在
这个节点不放人的合法方案数。
1:在
这个节点放人的合法方案数。
2:在
这个节点放人的不合法方案数。即在
这个节点放人,但是儿子节点上都没有人,
这个点是孤立的,但所有儿子的状态都是合法的。
#include<bits/stdc++.h>
const int MAX=1e6+10;
const int MOD=1e9+7;
using namespace std;
typedef long long ll;
vector<int>e[300];
ll d[210][210][3];
int n,m;
void dfs(int k,int fa)
{
d[k][0][0]=1;
d[k][1][2]=1;
for(int i=0;i<e[k].size();i++)
{
int nex=e[k][i];
if(nex==fa)continue;
dfs(nex,k);
for(int j=m;j>=1;j--)
{
for(int r=0;r<j;r++)//枚举儿子节点放的人数,r<j确保儿子节点至少放一个人
{
d[k][j][0]+=d[k][r][0]*((d[nex][j-r][0]+d[nex][j-r][1])%MOD)%MOD;
d[k][j][1]+=d[k][r][1]*((d[nex][j-r][2]+d[nex][j-r][1]+d[nex][j-r][0])%MOD)%MOD;
d[k][j][1]+=d[k][r][2]*((d[nex][j-r][2]+d[nex][j-r][1])%MOD)%MOD;
d[k][j][0]%=MOD;
d[k][j][1]%=MOD;
}
}
for(int j=m;j>=2;j--)//更新当前节点孤立的方案数
{
for(int r=1;r<j;r++)
{
d[k][j][2]+=d[k][r][2]*d[nex][j-r][0]%MOD;
d[k][j][2]%=MOD;
}
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++)e[i].clear();
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
}
memset(d,0,sizeof d);
dfs(1,0);
printf("%lld\n",(d[1][m][0]+d[1][m][1])%MOD);
}
return 0;
}