好题
qwq我承认我看了题解pwp
对树形dp不够熟悉,对题意转化不熟练。
题意就是说,对于任何一个点,其父亲或者儿子至少有一个被选中。
求恰好选中k个点的方案数。
对于这种可能被父亲管辖的dp,我们仍然设状态表示只被儿子管辖的可能。
父亲管辖体现在转移中。
我们设f[u][k][0/1][0/1]表示u点子树使用k个装置,u是否安放装置,u是否被管辖,u子树全都被管辖的方案数。
如果u点被父亲管辖,那么子节点爱放不放。反之必须放一个。如果u点放了,那子节点爱被管辖不被管辖。反之子节点必须被管辖
大型分类讨论现场
#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define in read()
int in{
int cnt=0,f=1;char ch=0;
while(!isdigit(ch)){
ch=getchar();if(ch=='-')f=-1;
}
while(isdigit(ch)){
cnt=cnt*10+ch-48;
ch=getchar();
}return cnt*f;
}
int f[100001][101][2][2];
int g[101][2][2];
int n,k;
int first[100003],nxt[200003],to[2000003],tot;
int size[100003];const int mod=1e9+7;
void Add(int a,int b){
nxt[++tot]=first[a];first[a]=tot;to[tot]=b;
}
int add(int a,int b){
return (a+b)>mod?(a+b-mod):(a+b);
}
int mul(int a,int b){
return (int)((ll)a*b%mod);
}
void dfs(int u,int faa){size[u]=1;f[u][0][0][0]=f[u][1][1][0]=1;
for(register int x=first[u];x;x=nxt[x]){
if(to[x]==faa)continue;dfs(to[x],u);
for(register int i=0;i<=min(size[u],k);i++){
g[i][0][0]=f[u][i][0][0];f[u][i][0][0]=0;
g[i][0][1]=f[u][i][0][1];f[u][i][0][1]=0;
g[i][1][0]=f[u][i][1][0];f[u][i][1][0]=0;
g[i][1][1]=f[u][i][1][1];f[u][i][1][1]=0;
}
for(register int i=0;i<=min(size[u],k);i++){
for(register int j=0;j<=min(size[to[x]],k-i);j++){
f[u][i+j][0][0]=add(f[u][i+j][0][0],mul(g[i][0][0],f[to[x]][j][0][1]));
f[u][i+j][0][1]=add(f[u][i+j][0][1],add(mul(g[i][0][0],f[to[x]][j][1][1]),mul(g[i][0][1],add(f[to[x]][j][0][1],f[to[x]][j][1][1]))));
f[u][i+j][1][0]=add(f[u][i+j][1][0],mul(g[i][1][0],add(f[to[x]][j][0][0],f[to[x]][j][0][1])));
f[u][i+j][1][1]=add(f[u][i+j][1][1],add(mul(g[i][1][0],(f[to[x]][j][1][1]+f[to[x]][j][1][0])),mul(g[i][1][1],add(f[to[x]][j][0][0],add(f[to[x]][j][0][1],add(f[to[x]][j][1][0],f[to[x]][j][1][1]))))));
}
}
size[u]+=size[to[x]];
}
}
signed main(){
n=in;k=in;
for(register int i=1;i<n;i++){
int a,b;a=in;b=in;Add(a,b);Add(b,a);
}
//cout<<mul(2,3)<<endl;
dfs(1,0);cout<<(add(f[1][k][0][1],f[1][k][1][1])%mod+mod)%mod;
return 0;
}