题意:给你一棵树,k个人,每颗树上只能安排一个人,每个人必须有另一个人相邻,问所有的方案总数。
题解:树形dp,三维的dp数组dp[i][j][3],前两维表示i的根数中站了j个人,0表示不站人的合法状态,1表示站人但是不合法状态,2表示站人的合法状态,然后就是一个dfs加dp
代码:
#include<bits/stdc++.h>
#define N 205
#define P pair<int,int>
using namespace std;
typedef long long ll;
const int M=1e9+7;
ll dp[N][N][3];
int k;
vector<int>v[N];
void dfs(int p,int fa)
{
dp[p][1][1]=1;
dp[p][0][0]=1;
for(int i=0;i<v[p].size();i++){
int u=v[p][i];
if(u==fa)continue;
dfs(u,p);
for(int j=k;j>=0;j--){
for(int x=1;x<=j;x++){
dp[p][j][0]+=dp[p][j-x][0]*(dp[u][x][0]+dp[u][x][2])%M;
//p的根数上站了j个人
//0表示p不站人的合法状态
dp[p][j][1]+=dp[p][j-x][1]*dp[u][x][0]%M;
//1表示p站人但是不合法状态
dp[p][j][2]+=dp[p][j-x][1]*(dp[u][x][1]+dp[u][x][2])%M;
//2表示p站人的合法状态
dp[p][j][2]+=dp[p][j-x][2]*(dp[u][x][0]+dp[u][x][1]+dp[u][x][2])%M;
for(int r=0;r<3;r++)
dp[p][j][r]%=M;
}
}
}
}
int main()
{
int n;
while(~scanf("%d%d",&n,&k))
{
for(int i=1;i<=n;i++)
v[i].clear();
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
memset(dp,0,sizeof(dp));
dfs(1,0);
printf("%d\n",(dp[1][k][0]+dp[1][k][2])%M);
}
return 0;
}