动态规划:树的最长路径 树形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;
}

 

posted @ 2022-04-27 10:53  朱朱成  阅读(175)  评论(0编辑  收藏  举报