C++---树形DP---树的最长路径(每日一道算法2023.5.4)

news2024/11/23 5:02:51

注意事项:
本题为"树与图的DFS深度优先遍历—树的重心"的近似题,同时涉及到 单链表模拟邻接表存储图 的操作,建议先理解那篇文章。

题目:
给定一棵树,树中包含 n 个结点(编号1~n)和 n−1 条无向边,每条边都有一个权值。
现在请你找到树中的一条最长路径。
换句话说,要找到一条路径,使得使得路径两端的点的距离最远。
注意:路径中可以只包含一个点。

输入格式
第一行包含整数 n。
接下来 n−1 行,每行包含三个整数 ai,bi,ci,表示点 ai 和 bi 之间存在一条权值为 ci 的边。

输出格式
输出一个整数,表示树的最长路径的长度。

数据范围
1≤n≤10000,
1≤ai,bi≤n,
−1e5≤ci≤1e5

输入:
6
5 1 6
1 4 5
6 3 9
2 6 8
6 1 7
输出:
22
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 10010, M = N*2;
int n, ans;                              //ans存储最终答案
int h[N], e[M], ne[M], w[M], idx = 0;     //单链表模拟邻接表

//邻接表增加一条边
void add(int a, int b, int c) {
    e[idx] = b;
    ne[idx] = h[a];
    w[idx] = c;
    h[a] = idx++;
}

//dfs数位dp,u是当前节点,f是当前节点的上一个节点(父节点)
int dfs(int u, int f) {
    int dist = 0;  //从当前点往下走的最大长度
    int d1 = 0, d2 = 0;   //表示挂在当前点上的最长路径d1和次长距离d2

    //枚举当前点i能到达的所有子节点j(遍历单链表)
    for (int i = h[u]; i!=-1; i=ne[i]) {
        int j = e[i];
        if (j == f) continue;   //由于是无向边,从a到b和从b到a都能走,但我们希望只能向下走,所以不能走回父节点

        int d = dfs(j, u) + w[i];   //子节点j往下走的最大长度 + j到i的边权
        dist = max(dist, d);

        //两种情况: 1.如果d大于等于d1,原本的最长路径就变为了次长路径,再把d存为最长路径 / 2.如果d不大于d1,但大于d2,直接更新即可
        if (d >= d1) {d2 = d1, d1 = d;}
        else if (d > d2) {d2 = d;}
    }

    ans = max(ans, d1+d2);    //d1+d2得到的就是穿过当前这个点的最长路径,因为一条最长向下的路 + 一条次长向下的路,合起来就是最长的路
    return dist;
}

int main() {
    //读入
    cin >> n;
    memset(h, -1, sizeof h);  //所有链头都指向-1即可
    for (int i = 0; i<n-1; i++) {  //n-1条无向边
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c); add(b, a, c);
    }

    dfs(1, -1);     //初始父节点随便设个不存在的就行
    cout << ans;

    return 0;
}

思路:
整体的思路不算难,首先,树可以被"拎起来",也就是可以随意挑一个点为根节点,
剩下的点都向下延申 (大家都见过二叉树吧?长得差不多,只不过可以有多个子节点)。

可以通过dfs来枚举所有路径的"最高"节点,假设当前路径为1-2-3,最高节点是2,
如何找到最高点为2的所有路径中的最长路径?
就是找到所有从节点2往下延申的路径中最长的那条和次长的那条,加起来即为答案:
请添加图片描述

还有更新最长和次长路径时会遇到的情况:
1.如果新的路径d大于等于d1,原本的最长路径就变为了次长路径,再把d存为最长路径
2.如果d不大于d1,但大于d2,直接更新即可

如果有所帮助请给个免费的赞吧~有人看才是支撑我写下去的动力!

声明:
算法思路来源为y总,详细请见https://www.acwing.com/
本文仅用作学习记录和交流

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/489227.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript:栈和对列

文章目录 栈和对列Js 有栈与队列吗20. 有效的括号 - 力扣&#xff08;LeetCode&#xff09;思路 1047. 删除字符串中的所有相邻重复项 - 力扣&#xff08;LeetCode&#xff09;思路代码分析array.join() 操作打印const s of str 操作遍历 150. 逆波兰表达式求值 - 力扣&#xf…

(1)QT基础铺垫

目录 1.Qt特性 2. 新建项目 3. 工作目录与构建目录 4. 工作目录 4.1 .pro 项目配置文件 4.2 dialog.h 4.3 dialog.cpp 4.4 main.cpp 5. 帮助文档 6. 调试信息 1.Qt特性 Qt经常被当作是一个基于c语言的gui开发框架&#xff0c;但是这并不是qt的全部&#xff0c;除了开…

助力工业物联网,工业大数据之ODS层构建:申明分区代码及测试【十】

文章目录 知识点13&#xff1a;ODS层构建&#xff1a;申明分区代码及测试知识点14&#xff1a;ODS层与DWD层区别知识点15&#xff1a;DWD层构建&#xff1a;需求分析知识点16&#xff1a;DWD层构建&#xff1a;建库实现测试知识点17&#xff1a;DWD层构建&#xff1a;建表实现测…

Packet Tracer – 研究 VLAN 实施

Packet Tracer – 研究 VLAN 实施 地址分配表 设备 接口 IP 地址 子网掩码 默认网关 S1 VLAN 99 172.17.99.31 255.255.255.0 不适用 S2 VLAN 99 172.17.99.32 255.255.255.0 不适用 S3 VLAN 99 172.17.99.33 255.255.255.0 不适用 PC1 NIC 172.17.10.2…

Linux部署Gitlab/上传项目

一、提前准备 1.1安装依赖工具 yum install -y curl policycoreutils-python openssh-serversystemctl start sshd systemctl enable sshd 1.2安装Postfix邮件服务器 #安装 postfix yum install -y postfix#启动 postfix 并设置为开机启动 systemctl enable postfix systemctl …

HashCode与String大家庭

当金钱站起来说话时&#xff0c;所有的真理都保持了沉默&#xff1b;金钱一旦作响&#xff0c;坏话随之戛然而止。 Hashcode的作用 java的集合有两类&#xff0c;一类是List&#xff0c;还有一类是Set 前者有序可重复&#xff0c;后者无序不重复。当我们在set中插入的时候怎…

Vue传参${id}变成$%7Bid%7D

发生缘由 外卖项目在Linux服务器上面运行发送请求乱码 运行环境 电脑系统&#xff1a;win10jdk版本&#xff1a;jdk-8SpringBoot版本&#xff1a;v2.4.5MP版本&#xff1a;3.4.2Vue版本&#xff1a;Vue.js v2.6.12Linux版本&#xff1a;Centos7 报错信息 // 修改页面反查详…

MES系统中的BOM为何如此重要?先进的BOM体系怎么构建?

其实不管有没有数字化&#xff0c;BOM都是制造企业的灵魂纽带&#xff0c;对于产品繁多、流程冗长的工业企业来说&#xff0c;如果BOM管理不规范&#xff0c;必然对生产效率和产品质量带来巨大的隐患&#xff0c;因此在工业企业的数字化转型之路中&#xff0c;建立科学规范的BO…

Blender 建模练习-锁链

目录 1.1.1 贝塞尔圆1.2 阵列修改器1.3 阵列修改器 物体偏移1.4 添加贝塞尔曲线1.5 曲线修改器 1. 本次练习主要使用到阵列修改器、贝塞尔曲线、空物体 1.1 贝塞尔圆 把贝塞尔圆进行缩放&#xff0c;然后在物体数据属性|几何数据|倒角|设置倒角深度为0.05 1.2 阵列修改器 …

【数据结构】二叉树(详细)

二叉树 1.树1.1定义1.2基本术语1.3树形结构和线性结构1.4树的存储结构1.4.1双亲表示法1.4.2孩子兄弟表示法 2.二叉树2.1定义2.2特殊二叉树2.3性质2.4存储结构2.4.1顺序存储2.4.2链式存储结构 3.二叉树的基本操作3.1前序遍历&#xff08;先序遍历&#xff09;3.2中序遍历3.3后序…

开放原子训练营(第三季)inBuilder低代码开发实验室---报销单录入系统

作为一名低代码初学者&#xff0c;我使用inBuilder系统设计了一款报销单录入系统&#xff0c;实现了报销单录入与显示报销单列表的功能&#xff08;如图1与图2所示&#xff09;&#xff0c;并获得了很多开发心得。从inBuilder系统的优点、缺点以及开发过程三方面出发&#xff0…

go继承nacos配置中心并读取配置信息

配置中心 为什么需要配置中心 平时我们写一个demo的时候&#xff0c;或者说一个单体的应用&#xff0c;都会有一个配置文件&#xff0c;不管是 json文件或者yaml文件&#xff0c;里面包含了redis,mysql,es等信息&#xff0c;如果我们修改了配置文件&#xff0c;往往我们需要重…

和Ai一起学习CMake(一)

和Ai一起学习CMake 现在人工智能爆火&#xff0c;ChatGPT、new bing等层出不穷。我们借助Ai来学习一下CMake。下面是我与Ai的问答&#xff0c;这个学习主要是通过Ai来学习&#xff0c;但是防止Ai乱说话&#xff0c;我会结合自身的知识和实际操作给出相应的补充。 我的环境如下…

玄子Share - Tomcat 9 安装配置教程(含安装包)

玄子Share - Tomcat 9 安装配置教程&#xff08;含安装包&#xff09; 下载 下载链接 官网 https://tomcat.apache.org/ 下载教程 进入 Tomcat 官网&#xff0c;点击左侧导航栏&#xff0c;选择需要的版本下载。这里按照课程要求选择tomcat 9的版本 Mirrors&#xff1a;选…

为什么越来越多的企业开始选择云计算?

一、前言 随着数字化时代的到来&#xff0c;企业对于数据的需求越来越大&#xff0c;而传统的数据存储方式已经无法满足企业的需求。云计算作为一种新兴的技术&#xff0c;可以为企业提供更加灵活、高效、安全的数据存储和处理方式&#xff0c;因此越来越多的企业开始选择云计算…

element ui el-calendar日历组件使用总结

el-calendar日历组件使用总结 1. 需求说明2. 基础实现3. 只展示当月数据4. 动态切换日历里的数据实现5. 顺便把快捷方式隐藏了&#xff0c;不让用户选择上一个月下一个月 1. 需求说明 按月显示&#xff0c;每次只显示一个月的日期&#xff0c;其余隐藏 日历组件的显示时间随着…

数值分析-牛顿插值公式

目录 一、引言 二、牛顿插值公式的基本概念 1.插值问题 2.插值多项式 3.牛顿插值公式 三、牛顿插值公式的推导过程 四、牛顿插值公式的应用 1.图像处理 2.信号处理 五、牛顿插值公式的优缺点 1. 优点 2. 缺点 六、总结 一、引言 在数值分析中&#xff0c;插值是一…

干掉复杂的Java工具类,Hutool 工具库确实香~

Hutool 大家已经比较熟悉了&#xff0c;这是一个超全的 Java 工具库&#xff0c;深受国内开发者的喜爱。 我之前其实是不太喜欢使用这种功能太多的工具类的&#xff0c;也比较担心稳定性和安全性&#xff0c;后面慢慢接受了就感觉其实也还好。而且&#xff0c;我们还可以按需只…

如何优雅地停掉线程?

很久很久以前&#xff0c;在一个名为“Springboot”的村庄中&#xff0c;住着一群热爱编程的程序员。他们喜欢探索新技术、优化自己的代码&#xff0c;为了打造更好的软件而不断努力着。 在这个村庄中&#xff0c;有一个名叫小明的程序员&#xff0c;他是村庄中最优秀的程序员…

等概率随机函数设计技巧

文章目录 1. 关于Math.random()函数2. 用1 ~ 5的随机函数加工出1 ~ 7的随机函数3. LeetCode 470. 用 Rand7() 实现 Rand10()4. 把不等概率随机函数变成等概率随机函数5. 用a ~ b的随机函数加工出c ~ d的随机函数 1. 关于Math.random()函数 Java 中 Math.random() 函数是等概率…