AcWing 1072:树的最长路径 ← 树形DP + 有权边
【题目来源】
【题目描述】
给定一棵树,树中包含 n 个结点(编号 1~n)和 n−1 条无向边,每条边都有一个权值。
现在请你找到树中的一条最长路径。
换句话说,要找到一条路径,使得路径两端的点的距离最远。
注意:路径中可以只包含一个点。
【输入格式】
第一行包含整数 n。
接下来 n−1 行,每行包含三个整数 ai,bi,ci,表示点 ai 和 bi 之间存在一条权值为 ci 的边。
【输出格式】
输出一个整数,表示树的最长路径的长度。
【输入样例】
6
5 1 6
1 4 5
6 3 9
2 6 8
6 1 7
【输出样例】
22
【数据范围】
1≤n≤10000,
1≤ai,bi≤n,
−10^5≤ci≤10^5
【算法分析】
● 什么是树的直径?树上任意两结点之间最长的简单路径即为树的直径。
若无负权边,可以采用两次 DFS 或者树形 DP 的方法在 O(n) 时间求出树的直径;若有负权边,则只能采用树形 DP 求解树的直径。显然,一棵树可以有多条直径,因为树中可能存在最长长度相等的多条简单路径。→ 推荐使用树形 DP 求解树的直径。
● 根据树形 DP 法原理,树的直径计算方法如下:
(1)路径定义:树的直径是树中任意两节点间最长的简单路径长度。
(2)状态转移:以某节点为根的子树,其延伸的最长路径长度记为 d1,次长路径长度记为 d2。树的直径即为所有节点 d1+d2 的最大值。
(3)路径特性:最长路径 d1 和次长路径 d2 无公共边,确保路径唯一性。
● 路径更新
若 d1[j]+1>d1[u],说明通过 j 的路径更长,更新 d1[u]=d1[j]+1,同时旧的最长路径 d1[u] 转为次长路径 d2[u]。
若 d1[j]+1<=d1[u] 但 d1[j]+1>d2[u],说明 j 的路径虽非最长,但比当前次长路径更长,更新 d2[u]=d1[j]+1。
● 更新方向
在树形 DP 中,路径长度从叶子节点(无子节点)开始计算,逐层向上更新父节点的路径长度。因此,j(子节点)确实会先于 u(父节点)被处理,符合“自下向上更新”的描述。
d1 和 d2 初始值为 0,表示所有节点的最长和次长路径长度从 0 开始计算,符合树形 DP 的初始化要求。
【算法代码一:有权边】
【算法代码二:无权边】
基于树边无权的情形,求树的直径的实例详见“洛谷 B4016:树的直径”。
详见:
【参考文献】

浙公网安备 33010602011771号