3760 最大剩余油量(树形dp)

1. 问题描述:

一个国家由 n 个城市组成,这 n 个城市由 n − 1 条双向道路连接,呈一个树形结构。每个城市都设有加油站,在第 i 个城市可以购买 wi 升汽油。汽车在道路上行驶,毫无疑问也会消耗汽油,每条道路的具体耗油量也会给出。现在,需要制定一条汽车的行进路线,从任意城市 s 出发,经过一条简单路径,到达任意城市 e 结束。注意,行进路线也可以只包含一个城市(也就是哪都没去)。汽车初始时油箱是空的,但是可以在路线中经过的每个城市购买汽油,包括开始城市和最终城市。如果在一条行进路线中,汽车沿一条道路从某一城市开往另一城市时,现有油量小于该条道路所需油量,那么就说明这条行进路线行不通。请问,在保证行进路线合理的情况下,汽车在抵达最终城市后,可以剩余的最大油量是多少?再次提醒,汽车在最终城市也可以加油。

输入格式

第一行包含整数 n。第二行包含 n 个整数 w1,w2,…,wn。接下来 n − 1 行,每行包含三个整数 u,v,c,表示城市 u 和城市 v 之间存在一条双向道路,耗油量为 c。

输出格式

一个整数,表示可能的最大剩余油量。

数据范围

前三个测试点满足,1 ≤ n ≤ 5。
所有测试点满足,1 ≤ n ≤ 3 × 10 ^ 5,0 ≤ wi ≤ 10 ^ 9,1 ≤ u,v ≤ n,1 ≤ c ≤ 10 ^ 9,u ≠ v。

输入样例1:

3
1 3 3
1 2 2
1 3 2

输出样例1:

3

输入样例2:

5
6 3 2 5 0
1 2 10
2 3 3
2 4 1
1 5 1

输出样例2:

7
来源:https://www.acwing.com/problem/content/description/3763/

2. 思路分析:

分析题目可以知道我们需要求解从一个点出发到达另外一个点的最长路径,类似于1072题树的最长路径,我们可以使用树形dp的思路来解决,树形dp其实也是枚举的思路,将所有的方案分类,枚举完所有的类之后可以将所有的方案枚举出来,对于这道题目来说我们可以枚举每一个节点作为最高点,由当前节点出发往下递归,在递归的过程中维护当前节点往下走的最长路径d1与次长路径d2这样以当前节点作为最高点的最长路径就可以求解出来,枚举每一个节点作为最高点的时候更新一下路径最大值,这样就可以求解出所有方案的最长路径。

3. 代码如下:

由于数据量最大是10 ^ 5,所以对于python来说递归这么大的深度肯定会爆栈,最终两个数据没过:

import sys
from typing import List


class Solution:
    res = 0

    def dfs(self, u: int, fa: int, w: List[int], g: List[List[int]]):
        d1 = d2 = 0
        for next in g[u]:
            # 由于是无向边所以需要传递父节点防止重复搜索
            if next[0] == fa: continue
            d = self.dfs(next[0], u, w, g)
            # 子节点无法到达父节点那么跳过, 因为假如父节点可以到达子节点而子节点不能够到达父节点那么走下去也是没有意义的因为此时最大距离更小还不如不走, 所以每一次由子节点的信息更新到父节点
            if d < next[1]: continue
            d -= next[1]
            # 更新子节点到父节点的距离
            if d > d1:
                d2 = d1
                d1 = d
            elif d > d2:
                d2 = d
        self.res = max(self.res, d1 + d2 + w[u])
        # 返回最大节点往下递归的最大距离
        return d1 + w[u]

    def process(self):
        n = int(input())
        w = [0] + list(map(int, input().split()))
        g = [list() for i in range(n + 10)]
        for i in range(n - 1):
            x, y, z = map(int, input().split())
            # 由于是无向边所以需要添加两个方向
            g[x].append((y, z))
            g[y].append((x, z))
        self.dfs(1, -1, w, g)
        return self.res


if __name__ == '__main__':
    sys.setrecursionlimit(10 ** 6)
    print(Solution().process())
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值