E82 树上背包 P4516 [JSOI2018] 潜入行动
视频链接:E82 树上背包 P4516 [JSOI2018] 潜入行动_哔哩哔哩_bilibili
P4516 [JSOI2018] 潜入行动 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
// 树上背包 O(n*k) #include<bits/stdc++.h> using namespace std; typedef long long LL; const int N=100005,mod=1000000007; int n,k,sz[N]; int f[N][105][2][2],g[105][2][2]; vector<int> e[N]; int add(LL x,LL y){ return (x+y)%mod; } void dfs(int u,int fa){ sz[u]=1; f[u][0][0][0]=f[u][1][1][0]=1; for(auto v:e[u]){ if(v==fa) continue; dfs(v,u); for(int i=0;i<=min(sz[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(int i=0;i<=min(sz[u],k);++i){ for(int j=0;j<=min(sz[v],k-i);++j){ f[u][i+j][0][0]=add(f[u][i+j][0][0], g[i][0][0]*1ll*f[v][j][0][1]); f[u][i+j][1][0]=add(f[u][i+j][1][0], g[i][1][0]*(1ll*f[v][j][0][0]+f[v][j][0][1])); f[u][i+j][0][1]=add(f[u][i+j][0][1], g[i][0][0]*1ll*f[v][j][1][1] +g[i][0][1]*(1ll*f[v][j][1][1]+f[v][j][0][1])); f[u][i+j][1][1]=add(f[u][i+j][1][1], +g[i][1][0]*(1ll*f[v][j][1][0]+f[v][j][1][1]) +g[i][1][1]*(1ll*f[v][j][0][0]+f[v][j][0][1] +f[v][j][1][0]+f[v][j][1][1])); } } sz[u]+=sz[v]; } } int main(){ scanf("%d%d",&n,&k); for(int i=1,u,v;i<n;++i){ scanf("%d%d",&u,&v); e[u].push_back(v); e[v].push_back(u); } dfs(1,0); printf("%d\n",(f[1][k][0][1]+f[1][k][1][1])%mod); }