版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/88362720
洛谷传送门
BZOJ传送门
解析:
挺简单的一道树形DP,应该是出题人不想让输出0的拿太多分所以深度设置较小,其实应该先求一遍直径来判断是否有解再进行DP,懒得写了 ,这样才能保证复杂度。
设 ,表示 的子树中(包括 )放置了总共 个监听器, 没放/放了,没被监听/被监听的方案数。
状态转移也非常好想,就在代码里面。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<20|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
re char c;
while(!isdigit(c=gc()));re int num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
}
using namespace IO;
cs int mod=1e9+7;
inline int add(cs int &a,cs int &b){return a+b>=mod?a+b-mod:a+b;}
inline void Add(int &a,cs int &b){(a+=b)>=mod?a-=mod:0;}
inline int dec(cs int &a,cs int &b){return a<b?a-b+mod:a-b;}
inline int mul(cs int &a,cs int &b){return (ll)a*b%mod;}
cs int N=1e5+5,K=1e2+2;
vector<int> edge[N];
inline void addedge(int u,int v){
edge[u].push_back(v);
edge[v].push_back(u);
}
int n,k;
int f[N][K][2][2],g[K][2][2];
int siz[N];
inline void dfs(cs int &u,cs int &fa){
f[u][0][0][0]=1;
f[u][1][1][0]=1;
siz[u]=1;
for(int re e=edge[u].size()-1,v;~e;--e)
if((v=edge[u][e])^fa){
dfs(v,u);
for(int re i=0,lim=min(siz[u],k);i<=lim;++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(int re i=0,lim1=min(k,siz[u]);i<=lim1;++i)
for(int re j=0,lim2=min(k-i,siz[v]);j<=lim2;++j){
Add(f[u][i+j][0][0],mul(g[i][0][0],f[v][j][0][1]));
Add(f[u][i+j][0][1],add(mul(g[i][0][0],f[v][j][1][1]),
mul(g[i][0][1],add(f[v][j][0][1],f[v][j][1][1]))));
Add(f[u][i+j][1][0],mul(g[i][1][0],add(f[v][j][0][1],f[v][j][0][0])));
Add(f[u][i+j][1][1],add(mul(g[i][1][0],add(f[v][j][1][1],f[v][j][1][0])),
mul(g[i][1][1],add(add(f[v][j][0][0],f[v][j][0][1]),
add(f[v][j][1][0],f[v][j][1][1])))));
}
siz[u]+=siz[v];
}
}
signed main(){
n=getint();k=getint();
for(int re i=1;i<n;++i)addedge(getint(),getint());
dfs(1,0);
cout<<add(f[1][k][1][1],f[1][k][0][1]);
return 0;
}