Codeforces274B
做法:树形dp,\(up[u]\)至少加多少次, \(down[u]\) 至少减多少次可以消去u这棵子树
转移:首先\(up[u] = max(up[v]), down[u] = max(down[u])\),因为为了消除整颗子树一定要选最多的次数才能消完,那么现在这个节点的\(a[u] = a[u] - down[u] + up[u]\),然后如果\(a[u]>0, down[u] += a[u]\), 如果\(a[u]<0, up[u] += (-a[u])\)
那么答案就是\(up[root] + down[root]\)
#include
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define pb push_back
typedef long long ll;
const int N = 1e5 + 7;
using namespace std;
int n;
vector g[N];
ll up[N],down[N],a[N];//up[u]: 至少加多少次, down[u]: 至少减多少次可以消去u这棵子树
void dfs(int u,int pre) {
for(auto v: g[u]) if(v!=pre){
dfs(v,u);
up[u] = max(up[u],up[v]);
down[u] = max(down[u],down[v]);
}
a[u] = a[u] - down[u] + up[u];
if(a[u]>=0) down[u] += a[u];
else up[u] += abs(a[u]);
}
int main() {
scanf("%d",&n);
int x,y;
rep(i,1,n-1) scanf("%d%d",&x,&y),g[x].pb(y),g[y].pb(x);
rep(i,1,n) scanf("%I64d",&a[i]);
dfs(1,0);
printf("%I64d\n",up[1]+down[1]);
return 0;
}