[USACO12FEB]附近的牛Nearby Cows

水题

19:46开始看题,20:09AC

就是大力dp啊,设dp[i][j]表示考虑到第i个点,距离它为j的数量,第一次倒推,求出子树中的,第二次正推,从父节点转移
转移见代码

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#define maxn 400006
#define int long long
#define SZJ signed
#include<time.h>
#define AK main
#define half (l+r)>>1
#define SDOI () 
#define mod 19650827
using namespace std;
#define rep(i,a,b) for (int (i)=(a);i<=(b);++(i)) 
#define dep(i,a,b) for (int (i)=(a);i>=(b);--(i))  
#define erep(i,a) for (int (i)=head[(a)];(i)!=-1;(i)=e[(i)].next)
#define lson t[s].lc
#define rson t[s].rc
#define MP make_pair
int head[maxn],cur,n,k,dp[maxn][25],size[maxn],val[maxn];
struct hzw
{
    int to,next;
}e[maxn];
inline void add(int a,int b)
{
    e[cur].to=b;
    e[cur].next=head[a];
    head[a]=cur++;
}
inline void dfs(int s,int fa)
{
    size[s]=1;
    dp[s][0]=val[s];
    erep(i,s)
    {
        if (e[i].to==fa) continue;
        dfs(e[i].to,s);
        size[s]+=size[e[i].to];
        rep(j,1,k) dp[s][j]+=dp[e[i].to][j-1]; 
    }
}	
int bef[25];
inline void dfs2(int s,int fa)
{
    if (s!=1)
    {
    
        rep(i,0,k) bef[i]=dp[s][i]; 
        dp[s][1]+=val[fa];
        rep(i,2,k)
        {
            dp[s][i]+=dp[fa][i-1];
            dp[s][i]-=bef[i-2];
        }
    }
    erep(i,s)
    {
        if (e[i].to==fa) continue;
        dfs2(e[i].to,s);
    }
}
int fina[maxn];
SZJ AK SDOI
{
    memset(head,-1,sizeof(head));
    cin>>n>>k;
    rep(i,1,n-1)
    {
        int a,b;
        scanf("%lld%lld",&a,&b);
        add(a,b);
        add(b,a);	
    } 
    rep(i,1,n) scanf("%lld",&val[i]);
    dfs(1,1);
    dfs2(1,1);
    rep(i,1,n) rep(j,0,k) fina[i]+=dp[i][j];
    rep(i,1,n) printf("%lld\n",fina[i]);
}
posted @ 2018-11-07 20:14  Splitor  阅读(139)  评论(0编辑  收藏  举报