luogu 3047 [USACO12FEB]附近的牛Nearby Cows 树形dp
$k$ 十分小,直接暴力维护 $1$~$k$ 的答案即可.
然后需要用父亲转移到儿子的方式转移一下.
Code:
#include <bits/stdc++.h> #define M 23 #define N 100005 #define setIO(s) freopen(s".in","r",stdin) using namespace std; int n,K,edges; int f[N][M],hd[N],to[N<<1],nex[N<<1],num[N],ans[N][M],sum[N][M]; void addedge(int u,int v) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; } void dfs(int u,int ff) { f[u][0]=num[u]; for(int i=hd[u];i;i=nex[i]) { int v=to[i]; if(v==ff) continue; dfs(v,u); for(int j=1;j<=K;++j) f[u][j]+=f[v][j-1]; } } void solve(int u,int ff) { ans[u][0]=num[u]; ans[u][1]=num[ff]+f[u][1]; for(int i=2;i<=K;++i) ans[u][i]=ans[ff][i-1]-f[u][i-2]+f[u][i]; for(int i=hd[u];i;i=nex[i]) if(to[i]!=ff) solve(to[i], u); } int main() { int i,j; // setIO("input"); scanf("%d%d",&n,&K); for(i=1;i<n;++i) { int a,b; scanf("%d%d",&a,&b),addedge(a,b),addedge(b,a); } for(i=1;i<=n;++i) scanf("%d",&num[i]); dfs(1,0); for(i=1;i<=n;++i) for(j=1;j<=K;++j) f[i][j]+=f[i][j-1]; for(i=1;i<=K;++i) ans[1][i]=f[1][i]; for(int i=hd[1];i;i=nex[i]) solve(to[i], 1); for(i=1;i<=n;++i) printf("%d\n",ans[i][K]); return 0; }