Codeforces 1084D - The Fair Nut and the Best Path - 树形DP

140 篇文章 0 订阅
80 篇文章 0 订阅

Codeforces 1084A - The Fair Nut and the Best Path - 树形DP

题解链接

https://lucien.ink


题目链接

https://codeforces.com/contest/1084/problem/D


题意

  给你一棵树,数上的每个点都有一个正权值,每条边都有一个负权值,让你在树中找一条简单路径,使得权值和最大。


思路

  我们定义 f i f_i fi 为从以节点 i i i 为根的子树中出发,到达节点 i i i 时的最大权值和,转移方程为:

f u = m a x { f v − c o s t u , v + w u } f_u = max\{f_v - cost_{u, v} + w_u\} fu=max{fvcostu,v+wu}

  这样处理的是竖着的路径,其中 v v v u u u 的每一个儿子。穿过节点 i i i 的横向路径的最大值为:

( f v 1 − c o s t u , v 1 ) 最 大 值 + ( f v 2 − c o s t u , v 2 ) 次 大 值 + w u ({f_{v_1} - cost_{u, v_1}})_{最大值} + ({f_{v_2} - cost_{u, v_2}})_{次大值} + w_u (fv1costu,v1)+(fv2costu,v2)+wu

  答案在所有 f i f_i fi 与上述表达式中取最大值,复杂度为 O ( n ) O(n) O(n)


实现

https://pasteme.cn/2421

#include <bits/stdc++.h>
const int maxn = int(3e5) + 7;
std::vector<std::pair<int, long long>> edge[maxn];
long long ans = 0, f[maxn];
int n, w[maxn];
void dfs(int u, int pre) {
    f[u] = w[u];
    long long max[2] = {0, 0};
    for (auto cur : edge[u]) {
        int v = cur.first;
        long long cost = cur.second;
        if (v != pre) {
            dfs(v, u);
            long long tmp = f[v] - cost;
            if (tmp > max[0]) std::swap(max[0], tmp);
            max[1] = std::max(max[1], tmp);
            f[u] = std::max(f[u], f[v] - cost + w[u]);
        }
    }
    ans = std::max({f[u], ans, max[0] + max[1] + w[u]});
}
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", w + i);
    for (int i = 1, u, v, cost; i < n; i++) {
        scanf("%d%d%d", &u, &v, &cost);
        edge[u].emplace_back(v, cost);
        edge[v].emplace_back(u, cost);
    }
    dfs(1, 1);
    printf("%lld\n", ans);
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值