做法:直接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; }