Codeforces274B

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 <bits/stdc++.h>
#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<int> 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;
}

猜你喜欢

转载自www.cnblogs.com/RRRR-wys/p/9438999.html