Codeforces Round #168 (Div. 1), problem: (B) Zero Tree, DFS

做法:直接DFS即可,题目要求最小的操作数其实可以理解成必须的操作数。

若 节点 x的值为a,a<0,则它的父节点必须做a次上升操作,a>0亦然,然后在看父节点经过这样的改造或的值,重复前面的运算即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;
const int LMT=100004;
LL elem[LMT],down[LMT],up[LMT];
int next[LMT],all;
struct line
{
    int u,v,next;
}e[LMT<<1];
void dfs(int u,int pre)
{
    LL uu,d;
    for(int x=next[u];x!=-1;x=e[x].next)
    if(e[x].v!=pre)
    {
        uu=d=0;
        dfs(e[x].v,u);
        if(elem[e[x].v]>0)
        {
            uu=up[e[x].v];
            d=down[e[x].v]+elem[e[x].v];
        }
        else
        {
            uu=up[e[x].v]-elem[e[x].v];
            d=down[e[x].v];
        }
        down[u]=max(d,down[u]);
        up[u]=max(uu,up[u]);
    }
    elem[u]+=up[u]-down[u];
}
void insert(int u,int v)
{
    e[all].u=u;
    e[all].v=v;
    e[all].next=next[u];
    next[u]=all++;
}
int main()
{
    memset(next,-1,sizeof(next));
    int n,u,v;
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&u,&v);
        insert(u,v);
        insert(v,u);
    }
    for(int i=1;i<=n;i++)scanf("%I64d",&elem[i]);
    dfs(1,0);
    printf("%I64d\n",abs(elem[1])+up[1]+down[1]);
    return 0;
}


你可能感兴趣的:(Codeforces Round #168 (Div. 1), problem: (B) Zero Tree, DFS)