动态规划:树的最长路径 树形DP
树的最长路径
题目描述
给定一棵树,树中包含 n 个结点(编号1~n)和 n−1 条无向边,每条边都有一个权值。
现在请你找到树中的一条最长路径。
换句话说,要找到一条路径,使得使得路径两端的点的距离最远。
注意:路径中可以只包含一个点。
输入格式
第一行包含整数 n。
接下来 n−1 行,每行包含三个整数 a b c
输出格式
输出一个整数,表示树的最长路径的长度。
数据范围
1 ≤ n ≤ 10000
1 ≤ a i , b i ≤ n
-1e5<=ci<=1e5
思路:
对每一个结点找到向下查找的max d1 和第二大 d2 则最大值就是d1+d2 更新ans 。相当于就是一条悬挂在结点上的最大路径。
关键dp代码:
这边的关键就是学会 更新d1 和 d2 更新的顺序很重要
完整代码:
#include<iostream> #include<algorithm> using namespace std; const int maxn = 1e4 + 5; int head[maxn], to[2 * maxn], nex[2 * maxn], val[2 * maxn], index;//邻接表 int n, a, b, c, ans; bool vis[maxn];//记录一下是否访问过 void add(int a, int b, int c) { index++; val[index] = c; to[index] = b; nex[index] = head[a]; head[a] = index; } int dfs(int u) { vis[u] = true; int d1 = 0, d2 = 0; for (int i = head[u]; i != -1; i = nex[i]) { int j = to[i]; if (vis[j]) continue;//避免向上查找 int d = dfs(j) + val[i]; if (d >= d1)//更新最大和次最大 要加等号 两个一样大的 可以为最大和次最大 { d2 = d1, d1 = d;//一定要先更新d2 再更新d1 } else if (d > d2) d2 = d; //cout << u << " " << d1 << " " << d2<<endl; } ans = max(ans, d1 + d2); // cout << u << " " << d1 << " " << d2<<" "<<ans<<endl; return d1; } int main() { memset(head, -1, sizeof(head));//初始化邻接表为-1 cin >> n; for (int i = 1; i < n; ++i) { cin >> a >> b >> c; add(a, b, c); add(b, a, c); } dfs(1); cout << ans; return 0; }