做法:直接DFS即可,題目要求最小的運算元其實可以理解成必須的運算元。
若 節點 x的值為a,a<0,則它的父節點必須做a次上升操作,a>0亦然,然後在看父節點經過這樣的改造或的值,重複前面的運算即可
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#define LL long longusing 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;}