【C++图论 BFS算法】2467. 树上最大得分和路径|2053

本文涉及知识点

C++图论
C++BFS算法

LeetCode2467. 树上最大得分和路径

一个 n 个节点的无向树,节点编号为 0 到 n - 1 ,树的根结点是 0 号节点。给你一个长度为 n - 1 的二维整数数组 edges ,其中 edges[i] = [ai, bi] ,表示节点 ai 和 bi 在树中有一条边。
在每一个节点 i 处有一扇门。同时给你一个都是偶数的数组 amount ,其中 amount[i] 表示:
如果 amount[i] 的值是负数,那么它表示打开节点 i 处门扣除的分数。
如果 amount[i] 的值是正数,那么它表示打开节点 i 处门加上的分数。
游戏按照如下规则进行:
一开始,Alice 在节点 0 处,Bob 在节点 bob 处。
每一秒钟,Alice 和 Bob 分别 移动到相邻的节点。Alice 朝着某个 叶子结点 移动,Bob 朝着节点 0 移动。
对于他们之间路径上的 每一个 节点,Alice 和 Bob 要么打开门并扣分,要么打开门并加分。注意:
如果门 已经打开 (被另一个人打开),不会有额外加分也不会扣分。
如果 Alice 和 Bob 同时 到达一个节点,他们会共享这个节点的加分或者扣分。换言之,如果打开这扇门扣 c 分,那么 Alice 和 Bob 分别扣 c / 2 分。如果这扇门的加分为 c ,那么他们分别加 c / 2 分。
如果 Alice 到达了一个叶子结点,她会停止移动。类似的,如果 Bob 到达了节点 0 ,他也会停止移动。注意这些事件互相 独立 ,不会影响另一方移动。
请你返回 Alice 朝最优叶子结点移动的 最大 净得分。
示例 1:

在这里插入图片描述

输入:edges = [[0,1],[1,2],[1,3],[3,4]], bob = 3, amount = [-2,4,2,-4,6]
输出:6
解释:
上图展示了输入给出的一棵树。游戏进行如下:

  • Alice 一开始在节点 0 处,Bob 在节点 3 处。他们分别打开所在节点的门。
    Alice 得分为 -2 。
  • Alice 和 Bob 都移动到节点 1 。
    因为他们同时到达这个节点,他们一起打开门并平分得分。
    Alice 的得分变为 -2 + (4 / 2) = 0 。
  • Alice 移动到节点 3 。因为 Bob 已经打开了这扇门,Alice 得分不变。
    Bob 移动到节点 0 ,并停止移动。
  • Alice 移动到节点 4 并打开这个节点的门,她得分变为 0 + 6 = 6 。
    现在,Alice 和 Bob 都不能进行任何移动了,所以游戏结束。
    Alice 无法得到更高分数。
    示例 2:
    在这里插入图片描述

输入:edges = [[0,1]], bob = 1, amount = [-7280,2350]
输出:-7280
解释:
Alice 按照路径 0->1 移动,同时 Bob 按照路径 1->0 移动。
所以 Alice 只打开节点 0 处的门,她的得分为 -7280 。

提示:
2 <= n <= 105
edges.length == n - 1
edges[i].length == 2
0 <= ai, bi < n
ai != bi
edges 表示一棵有效的树。
1 <= bob < n
amount.length == n
amount[i] 是范围 [-104, 104] 之间的一个 偶数 。

BFS

本方法用BFS代替DFS,来达到提速的目的。时间复杂度:O(m),m是边的数量。
一,将边转成邻接表neiBo。
二,BFS邻接表获取各节点层次leve。
三,通过各节点层次获取各层次包括节点leveNodes。
四,通过边和节点层次获取各节点的父节点pars。
五,通过par节点bob到达各节点时间bomTime,无法到达为n+1。
六,层次从小到大处理个节点。ans[cur]记录alice到达时的得分:父节点的得分+本节点得法。如果leve > bomTime[cur],不得分;相等,得一半的分;小于,得全分。
七,求ans[cur]的最大值,cur是叶子节点。 如果只有一个节点,唯一的节点是根,也是叶子。否则,根不是叶子,其它节点是否是叶子节点 ⟺ \iff neiBo[cur].size()是否是1。

代码

核心代码

class CNeiBo
{
public:	static vector<vector<int>> Two(int n, vector<vector<int>>& edges, bool bDirect, int iBase = 0) {vector<vector<int>>  vNeiBo(n);for (const auto& v : edges){vNeiBo[v[0] - iBase].emplace_back(v[1] - iBase);if (!bDirect){vNeiBo[v[1] - iBase].emplace_back(v[0] - iBase);}}return vNeiBo;}	static vector<vector<std::pair<int, int>>> Three(int n, vector<vector<int>>& edges, bool bDirect, int iBase = 0){vector<vector<std::pair<int, int>>> vNeiBo(n);for (const auto& v : edges){vNeiBo[v[0] - iBase].emplace_back(v[1] - iBase, v[2]);if (!bDirect){vNeiBo[v[1] - iBase].emplace_back(v[0] - iBase, v[2]);}}return vNeiBo;}	static vector<vector<int>> Mat(vector<vector<int>>& neiBoMat){vector<vector<int>> neiBo(neiBoMat.size());for (int i = 0; i < neiBoMat.size(); i++){for (int j = i + 1; j < neiBoMat.size(); j++){if (neiBoMat[i][j]){neiBo[i].emplace_back(j);neiBo[j].emplace_back(i);}}}return neiBo;}
};class CBFSLeve {
public :static vector<int> Leve(const vector<vector<int>>& neiBo, vector<int> start) {vector<int> leves(neiBo.size(), -1);for (const auto& s : start) {leves[s] = 0;}for (int i = 0; i < start.size(); i++) {for (const auto& next : neiBo[start[i]]) {if (-1 != leves[next]) { continue; }leves[next] = leves[start[i]] + 1;start.emplace_back(next);}}return leves;}template<class NextFun>static vector<int> Leve(int N,NextFun nextFun, vector<int> start) {vector<int> leves(N, -1);for (const auto& s : start) {leves[s] = 0;}for (int i = 0; i < start.size(); i++) {auto nexts = nextFun(start[i]);for (const auto& next : nexts) {if (-1 != leves[next]) { continue; }leves[next] = leves[start[i]] + 1;start.emplace_back(next);}}return leves;}static vector<vector<int>> LeveNodes(const vector<int>& leves) {const int iMaxLeve = *max_element(leves.begin(), leves.end());vector<vector<int>> ret(iMaxLeve + 1);for (int i = 0; i < leves.size(); i++) {ret[leves[i]].emplace_back(i);}return ret;};
};
class Solution {public:int mostProfitablePath(vector<vector<int>>& edges, int bob, vector<int>& amount) {const int N = amount.size();auto neiBo = CNeiBo::Two(N, edges, false);auto leves = CBFSLeve::Leve(neiBo, { 0 });auto leveNodes = CBFSLeve::LeveNodes(leves);vector<int> par(N, -1);for (const auto& v : edges) {if (leves[v[0]] < leves[v[1]]) {par[v[1]] = v[0];}else {par[v[0]] = v[1];}}vector<int> bomTime(N, N + 1);for (int i = 0; bob != -1; bob = par[bob], i++) {bomTime[bob] = i;}vector<int> ans(N);for (int i = 0; i < leveNodes.size();i++) {const auto& nodes = leveNodes[i];for (const auto& cur : nodes) {if (-1 != par[cur])	{ans[cur] += ans[par[cur]];	}if (bomTime[cur] < i) { continue; }if (bomTime[cur] > i) {ans[cur] += amount[cur];}else {ans[cur] += amount[cur] / 2;}}}int iAns = INT_MIN;for (int i = 1; i < N; i++) {if (neiBo[i].size() != 1)continue;iAns = max(iAns, ans[i]);}return iAns;}};

单元测试

vector<vector<int>> edges;int bob ;vector<int> amount;TEST_METHOD(TestMethod1){edges = { {0,1},{1,2},{1,3},{3,4} }, bob = 3, amount = { -2,4,2,-4,6 };auto res = Solution().mostProfitablePath(edges, bob, amount);AssertEx(6, res);}TEST_METHOD(TestMethod2){edges = { {0,1} }, bob = 1, amount = { -7280,2350 };auto res = Solution().mostProfitablePath(edges, bob, amount);AssertEx(-7280, res);}	

扩展阅读

我想对大家说的话
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛
失败+反思=成功 成功+反思=成功

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mysql | 尚硅谷 | 第02章_MySQL环境搭建

Mysql笔记&#xff1a;第02章_MySQL环境搭建 说明&#xff1a;本内容整理自尚硅谷B站MySQL视频>>尚硅谷B站MySQL视频 文章目录 Mysql笔记&#xff1a;第02章_MySQL环境搭建第02章_MySQL环境搭建 1. MySQL的卸载步骤1&#xff1a;停止MySQL服务步骤2&#xff1a;[软件](h…

【网络篇】TCP知识

TCP首部格式&#xff1f; 为什么需要 TCP 协议&#xff1f; TCP 工作在哪一层&#xff1f; IP 层是不可靠的&#xff0c;它不保证网络包的交付、不保证网络包的按序交付也不保证网络包中的数据的完整性。如果需要保障网络数据包的可靠性&#xff0c;那么就需要由上层&#xff0…

Spring Boot漫画之家:漫画爱好者的数字图书馆

2 系统开发环境 2.1 JAVA简介 JavaScript是一种网络脚本语言&#xff0c;广泛运用于web应用开发&#xff0c;可以用来添加网页的格式动态效果&#xff0c;该语言不用进行预编译就直接运行&#xff0c;可以直接嵌入HTML语言中&#xff0c;写成js语言&#xff0c;便于结构的分离&…

一次“okhttp访问间隔60秒,提示unexpected end of stream“的问题排查过程

一、现象 okhttp调用某个服务&#xff0c;如果第二次访问间隔上一次访问时间超过60s&#xff0c;返回错误&#xff1a;"unexpected end of stream"。 二、最终定位原因&#xff1a; 空闲连接如果超过60秒&#xff0c;服务端会主动关闭连接。此时客户端恰巧访问了这…

一、开启 GD32 单片机的学习之门

文章目录 一、开启GD32单片机的学习之门二、筑牢根基&#xff1a;GD32单片机基础知识全解析&#xff08;一&#xff09;单片机概述 三、开发环境搭建&#xff08;一&#xff09;软件下载与安装&#xff08;二&#xff09;安装GD32F450设备支持包&#xff08;三&#xff09;编译…

渗透测试---burpsuite(6)暴力破解与验证码识别绕过

声明&#xff1a;学习素材来自b站up【泷羽Sec】&#xff0c;侵删&#xff0c;若阅读过程中有相关方面的不足&#xff0c;还请指正&#xff0c;本文只做相关技术分享,切莫从事违法等相关行为&#xff0c;本人与泷羽sec团队一律不承担一切后果 视频地址&#xff1a;泷羽---bp&…

PSHuman 部署笔记

目录 github地址&#xff1a; 依赖项&#xff1a; xformers安装&#xff1a; 解决方法&#xff0c;安装xformers smpl_data下载&#xff1a; 推理步骤&#xff1a; SMPLDataset 香港科技大学提出了一种叫PSHuman的新框架。这个方法利用了一个多视角扩散模型的“先验知识…

基于VTX356语音识别合成芯片的智能语音交互闹钟方案

一、方案概述 本方案旨在利用VTX356语音识别合成芯片强大的语音处理能力&#xff0c;结合蓝牙功能、APP或小程序&#xff0c;打造一款功能全面且智能化程度高的闹钟产品。除了基本的时钟显示和闹钟提醒功能外&#xff0c;还拥有正计时、倒计时、日程安排、重要日提醒以及番茄钟…

20241206-Windows 10下使用IDEA 2024.2.3(JDK 18.0.2.1)搭建Hadoop 3.3.6开发环境

Windows 10下使用IDEA 2024.2.3(JDK 18.0.2.1)搭建Hadoop 3.3.6开发环境 1. 配置好本地hadoop之后 2. idea 新建或导入 Maven 项目 3. 编写 pom.xml 文件: 有些版本和项目信息需要根据自己的项目进行调整 JDK 18.0.2.1 Hadoop 3.3.6 <?xml version"1.0" encod…

如何使用WinCC DataMonitor基于Web发布浏览Excel报表文档

本文介绍使用 WinCC DataMonitor 的 "Excel Workbooks" 功能&#xff0c;通过 Excel 表格显示 WinCC 项目的过程值、归档变量值和报警归档消息。并可以通过 Web 发布浏览访问数据 1&#xff0e;WinCC DataMonitor是什么 ? DataMonitor 是 SIMATIC WinCC 工厂智能中…

Fastadmin地图插件在表单中的使用

表单中实现地图选择获取经纬度 1.Fastadmin后台安装地图选择插件地图位置(经纬度)选择插件 - 支持百度地图、高德地图、腾讯地图 – 基于ThinkPHP和Bootstrap的极速后台开发框架 2.腾讯地图开放平台后台创建应用创建KEY&#xff0c;配置逆地址解析额度。插件配置中配置腾讯地图…

解决view-ui-plus 中表单验证不通过问题,select 组件开启multiple模式 总是提示错误,即使不验证也提示,有值也验证失败

&#x1f609; 你好呀&#xff0c;我是爱编程的Sherry&#xff0c;很高兴在这里遇见你&#xff01;我是一名拥有十多年开发经验的前端工程师。这一路走来&#xff0c;面对困难时也曾感到迷茫&#xff0c;凭借不懈的努力和坚持&#xff0c;重新找到了前进的方向。我的人生格言是…

JDK8新特性之Stream流03

收集Stream流中的结果 IntStream intStream = Stream.of(1, 2, 3, 4, 5).mapToInt(Integer::intValue); intStream.filter(n -> n > 3).forEach(System.out::println); intStream.filter(n -> n > 3).count; intStream.filter(n -> n > 3).reduce(0, Integer…

图社区发现算法--Leiden算法

Leiden算法出自2019年的论文《From Louvain to Leiden: guaranteeing well-connected communities》&#xff0c;它是Louvain算法的改进社区发现算法&#xff0c;相比Louvain得到的社区质量更高&#xff0c;因为其移动策略速度也更快。Leiden算法也是以论文作者所在城市来命名的…

基于APO四步实现炫酷的NGINX请求分析看板

APO 充分利用 Vector ClickHouse 实现的日志方案&#xff0c;做到了开箱即用、高效、低成本。利用 APO 的日志功能&#xff0c;不仅可以检索日志内容本身&#xff0c;还可以实现很多有意思的功能。本次为大家介绍使用 APO 的日志功能实现炫酷的 NGINX 请求分析看板&#xff0c…

QT 中基于 TCP 的网络通信

基础 基于 TCP 的套接字通信需要用到两个类&#xff1a; 1&#xff09;QTcpServer&#xff1a;服务器类&#xff0c;用于监听客户端连接以及和客户端建立连接。 2&#xff09;QTcpSocket&#xff1a;通信的套接字类&#xff0c;客户端、服务器端都需要使用。 这两个套接字通信类…

X推出新AI图像生成器Aurora:更接近真实的创作效果

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

后端工程搭建

后端工程通过maven聚合工程的形式来搭建 1.1创建spzx-parent工程(父工程) 存放公共依赖 锁定公共依赖版本 1.2创建spzx-common工程(公共模块) 存放一些工具类/公共服务 1.3创建spzx-model工程(数据模型) 存放实体类 1.4创建spzx-menager工程(后台管理系统) 后台管理系统服务模…

Co-Slam论文及复现记录

Overview 输入RGB-D流&#xff1a; { I t } t 1 N { D t } t 1 N \{I_t\}^{N}_{t1}\{D_t\}^{N}_{t1} {It​}t1N​{Dt​}t1N​&#xff0c;它们带有已知相机内参 K ∈ R 3 3 K\in \mathbb{R}^{3\times 3} K∈R33。通过联合优化相机姿态 { ξ t } t 1 N \{\xi_t\}^{N}_{t1} {…

无代码,无问题:面向手动测试人员的人工智能自动化

“质量比数量更重要。一个本垒打比两个二垒打好得多。” ——史蒂夫乔布斯 在软件测试领域&#xff0c;这句话再贴切不过了。如果你是一名手动测试人员&#xff0c;你就会知道交付高质量结果的压力&#xff0c;而且通常是在紧迫的期限和有限的资源内。 然而&#xff0c;在当今…