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; 
}

  

posted @ 2019-09-24 14:14  EM-LGH  阅读(136)  评论(0编辑  收藏  举报