Codeforces 274B 【树形DP】

题目大意
给定一棵树,以及树上每个点的权值,每次操作可以将一棵含有节点1的联通子集上的所有的点权全部加1或减1,求最少几次操作可以将树上全部点权变为0

根据题意,设1点为树根,这样对每个点修改时,一定也会修改其父节点,因为它的父节点是通往(1号点/树根)的必经之路

这样的话就是YY一个使得总操作次数最少的方法了。如果我们能够把几个个点权值变为0的过程合为同一次操作,那样次数就会变少,如果说一个点有多个儿子,那么对于这多个儿子来说只需要取最大的操作次数就行,小于这个操作次数的儿子节点们,他们可以在对这个儿子操作的过程中顺便清0,只是不需要那么多次数罢了
设对于一个点所有的加1操作的次数为up(u),减1操作的次数为down(u)
则有

up[u]=max(up[v])(vuson) u p [ u ] = m a x ( u p [ v ] ) ( v ∈ u s o n )

down[u]同理
当然,转移之后的up[u] down[u]可能并不会正好使u点权值为0,只要再根据u点本来的权值加加减减就能得出最后的up[u] down[u]
最后答案就是up[1]+down[1]

有个点得说说
if(w[u] < 0) up[u] -= w[u];
这里,w[u]是负数。
而up[u]存储的是操作次数,是一个绝对值,所以要负负得正Orz


这题给我的启示
先想简单的 只有两个点 一个是1 一个是2
然后想一条链该怎么做
想一条链的时候,这个链的末尾如果出现了分支怎么办
然后在链的中间出现分支
这样就得到了一棵树的做法
也就是说 让一个点慢慢长成一棵树 从链到树
因为我习惯把部分分都打完,一般树的问题都会给一条链的分,而正解又是从一条链上来的
另外 noip的树上问题要么lca要么dp或者树剖,但是树剖其实也是在求树上路径和lca
这就是逻辑…由简单到复杂 由局部推广到全局

#include <cstdio>
#include <iostream>
#include <algorithm>
const int maxn = 100010;
using namespace std;
int n,last[maxn],tot;
long long up[maxn],down[maxn],w[maxn];
struct Edge{
    int u,v,to;
    Edge(){}
    Edge(int u, int v, int to) : u(u), v(v), to(to) {}
}e[maxn*2];
inline void addedge(int u, int v) {
    e[++tot] = Edge(u,v,last[u]);
    last[u] = tot;
}
void dfs(int u, int parent) {
    for(int i=last[u]; i; i=e[i].to) {
        int v = e[i].v;
        if(v==parent) continue;
        dfs(v, u);
        up[u] = max(up[u], up[v]);
        down[u] = max(down[u], down[v]);
    }
    w[u] += up[u] - down[u];
    if(w[u] > 0) down[u] += w[u];
    if(w[u] < 0) up[u] -= w[u];
}
int main() {
    scanf("%d",&n);
    for(int i=1; i<n; i++) {
        int u, v;
        scanf("%d %d",&u, &v);
        addedge(u,v);
        addedge(v,u);
    }
    for(int i=1; i<=n; i++)
        scanf("%I64d", &w[i]);
    dfs(1,-2);  
    printf("%I64d",up[1] + down[1]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值