【深度优先搜索】【树】【图论】2973. 树中每个节点放置的金币数目

作者推荐

视频算法专题

本博文涉及知识点

深度优先搜索 树 图论 分类讨论

LeetCode2973. 树中每个节点放置的金币数目

给你一棵 n 个节点的 无向 树,节点编号为 0 到 n - 1 ,树的根节点在节点 0 处。同时给你一个长度为 n - 1 的二维整数数组 edges ,其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 之间有一条边。
给你一个长度为 n 下标从 0 开始的整数数组 cost ,其中 cost[i] 是第 i 个节点的 开销 。
你需要在树中每个节点都放置金币,在节点 i 处的金币数目计算方法如下:
如果节点 i 对应的子树中的节点数目小于 3 ,那么放 1 个金币。
否则,计算节点 i 对应的子树内 3 个不同节点的开销乘积的 最大值 ,并在节点 i 处放置对应数目的金币。如果最大乘积是 负数 ,那么放置 0 个金币。
请你返回一个长度为 n 的数组 coin ,coin[i]是节点 i 处的金币数目。
示例 1:
在这里插入图片描述

输入:edges = [[0,1],[0,2],[0,3],[0,4],[0,5]], cost = [1,2,3,4,5,6]
输出:[120,1,1,1,1,1]
解释:在节点 0 处放置 6 * 5 * 4 = 120 个金币。所有其他节点都是叶子节点,子树中只有 1 个节点,所以其他每个节点都放 1 个金币。
示例 2:
在这里插入图片描述

输入:edges = [[0,1],[0,2],[1,3],[1,4],[1,5],[2,6],[2,7],[2,8]], cost = [1,4,2,3,5,7,8,-4,2]
输出:[280,140,32,1,1,1,1,1,1]
解释:每个节点放置的金币数分别为:

  • 节点 0 处放置 8 * 7 * 5 = 280 个金币。
  • 节点 1 处放置 7 * 5 * 4 = 140 个金币。
  • 节点 2 处放置 8 * 2 * 2 = 32 个金币。
  • 其他节点都是叶子节点,子树内节点数目为 1 ,所以其他每个节点都放 1 个金币。
    示例 3:
    在这里插入图片描述

输入:edges = [[0,1],[0,2]], cost = [1,2,-2]
输出:[0,1,1]
解释:节点 1 和 2 都是叶子节点,子树内节点数目为 1 ,各放置 1 个金币。节点 0 处唯一的开销乘积是 2 * 1 * -2 = -4 。所以在节点 0 处放置 0 个金币。

提示:
2 <= n <= 2 * 104
edges.length == n - 1
edges[i].length == 2
0 <= ai, bi < n
cost.length == n
1 <= |cost[i]| <= 104
edges 一定是一棵合法的树。

分类讨论

情况表面上很多,时间上只有4情况:
{ 1 不足 3 个节点 最大的三个正数的乘积 至少 3 个正数节点 1 个正数和 2 个负数的乘积 至少一个正数节点, 2 个负数节点 0 o t h e r \begin{cases} 1 &不足3个节点 \\ 最大的三个正数的乘积 & 至少3个正数节点\\ 1个正数和2个负数的乘积 & 至少一个正数节点,2个负数节点\\ 0 & other \\ \end{cases} 1最大的三个正数的乘积1个正数和2个负数的乘积0不足3个节点至少3个正数节点至少一个正数节点,2个负数节点other
正数节点都只需要记录3个节点,2个不够。

3个负数节点,0个正数节点。值是0。
2个负数节点,0个正数节点。值是1。
注意:cost[i]不会为0。

代码

核心代码

class CNeiBo2
{
public:CNeiBo2(int n, bool bDirect, int iBase = 0) :m_iN(n), m_bDirect(bDirect), m_iBase(iBase){m_vNeiB.resize(n);}CNeiBo2(int n, vector<vector<int>>& edges, bool bDirect, int iBase = 0) :m_iN(n), m_bDirect(bDirect), m_iBase(iBase){m_vNeiB.resize(n);for (const auto& v : edges){m_vNeiB[v[0] - iBase].emplace_back(v[1] - iBase);if (!bDirect){m_vNeiB[v[1] - iBase].emplace_back(v[0] - iBase);}}}inline void Add(int iNode1, int iNode2){iNode1 -= m_iBase;iNode2 -= m_iBase;m_vNeiB[iNode1].emplace_back(iNode2);if (!m_bDirect){m_vNeiB[iNode2].emplace_back(iNode1);}}const int m_iN;const bool m_bDirect;const int m_iBase;vector<vector<int>> m_vNeiB;
};class Solution {
public:vector<long long> placedCoins(vector<vector<int>>& edges, vector<int>& cost) {m_vAns.resize(cost.size());m_cost = cost;CNeiBo2 neiBo(cost.size(), edges, false);std::priority_queue<int> maxHeap;std::priority_queue<int, vector<int>, greater<int> > minHeap;DFS(maxHeap, minHeap, neiBo.m_vNeiB, 0, -1);return m_vAns;}void DFS(std::priority_queue<int>& maxHeap, std::priority_queue<int, vector<int>, greater<int> >& minHeap,const vector<vector<int>>& neiBo, int cur, int par){if (m_cost[cur] >= 0){minHeap.emplace(m_cost[cur]);}else{maxHeap.emplace(m_cost[cur]);}for (const auto& next : neiBo[cur]){if (next == par){continue;}std::priority_queue<int> maxHeap1;std::priority_queue<int, vector<int>, greater<int> > minHeap1;DFS(maxHeap1,minHeap1,neiBo, next, cur);Union(maxHeap, maxHeap1);Union(minHeap, minHeap1);}auto Cal = [&](){if (maxHeap.size() + minHeap.size() <3 ){return 1LL;} long long llRet = 0;auto v1 = ToVector(minHeap);auto v2 = ToVector(maxHeap);			if (3 == minHeap.size()){		llRet =max(llRet, (long long)v1[0] * v1[1] * v1[2]);}if (minHeap.size()&& (maxHeap.size() >= 2)){				if (v2.size() > 2){v2.erase(v2.begin());}				llRet = max(llRet, (long long)v1.back() * v2[0] * v2[1]);}return llRet;};m_vAns[cur] = Cal();}protected:template<class T>vector<int> ToVector(T heap){vector<int> v;while (heap.size()){v.emplace_back(heap.top());heap.pop();}T heap2(v.begin(), v.end());heap2.swap(heap);return v;}template<class T>void Union(T& heap1, T& heap2){while (heap2.size()){heap1.emplace(heap2.top());heap2.pop();}while (heap1.size() > 3){heap1.pop();}}vector<long long> m_vAns;vector<int> m_cost;
};

测试用例

template<class T,class T2>
void Assert(const T& t1, const T2& t2)
{assert(t1 == t2);
}template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{if (v1.size() != v2.size()){assert(false);return;}for (int i = 0; i < v1.size(); i++){Assert(v1[i], v2[i]);}}int main()
{vector<vector<int>> edges;vector<int> cost;{Solution sln;edges = { {0,1},{0,2},{2,3} }, cost = { 10000, -10000, 10000, -10000 };auto res = sln.placedCoins(edges, cost);Assert({ 1000000000000,1,1,1 }, res);}{Solution sln;edges = { {0,1},{0,2},{0,3},{0,4},{0,5} }, cost = { 1,2,3,4,5,6 };auto res = sln.placedCoins(edges, cost);Assert({ 120,1,1,1,1,1 }, res);}{Solution sln;edges = { {0,1},{0,2},{1,3},{1,4},{1,5},{2,6},{2,7},{2,8} }, cost = { 1,4,2,3,5,7,8,-4,2 };auto res = sln.placedCoins(edges, cost);Assert({ 280,140,32,1,1,1,1,1,1 }, res);}{Solution sln;edges = { {0,1},{0,2} }, cost = { 1,2,-2 };auto res = sln.placedCoins(edges, cost);Assert({ 0,1,1 }, res);}{Solution sln;edges = { {0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11},{0,12},{0,13},{0,14},{0,15},{0,16},{0,17},{0,18},{0,19},{0,20},{0,21},{0,22},{0,23},{0,24},{0,25},{0,26},{0,27},{0,28},{0,29},{0,30},{0,31},{0,32},{0,33},{0,34},{0,35},{0,36},{0,37},{0,38},{0,39},{0,40},{0,41},{0,42},{0,43},{0,44},{0,45},{0,46},{0,47},{0,48},{0,49},{0,50},{0,51},{0,52},{0,53},{0,54},{0,55},{0,56},{0,57},{0,58},{0,59},{0,60},{0,61},{0,62},{0,63},{0,64},{0,65},{0,66},{0,67},{0,68},{0,69},{0,70},{0,71},{0,72},{0,73},{0,74},{0,75},{0,76},{0,77},{0,78},{0,79},{0,80},{0,81},{0,82},{0,83},{0,84},{0,85},{0,86},{0,87},{0,88},{0,89},{0,90},{0,91},{0,92},{0,93},{0,94},{0,95},{0,96},{0,97},{0,98},{0,99} };cost={-5959, 602, -6457, 7055, -1462, 6347, 7226, -8422, -6088, 2997, -7909, 6433, 5217, 3294, -3792, 7463, 8538, -3811, 5009, 151, 5659, 4458, -1702, -1877, 2799, 9861, -9668, -1765, 2181, -8128, 7046, 9529, 6202, -8026, 6464, 1345, 121, 1922, 7274, -1227, -9914, 3025, 1046, -9368, -7368, 6205, -6342, 8091, -6732, -7620, 3276, 5136, 6871, 4823, -1885, -4005, -3974, -2725, -3845, -8508, 7201, -9566, -7236, -3386, 4021, 6793, -8759, 5066, 5879, -5171, 1011, 1242, 8536, -8405, -9646, -214, 2251, -9934, -8820, 6206, 1006, 1318, -9712, 7230, 5608, -4601, 9185, 346, 3056, 8913, -2454, -3445, -4295, 4802, -8852, -6121, -4538, -5580, -9246, -6462};auto res = sln.placedCoins(edges, cost);sort(cost.begin(), cost.end());Assert({ 971167251036, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, res);}
}

第二版

class CNeiBo2
{
public:
CNeiBo2(int n, bool bDirect, int iBase = 0) :m_iN(n), m_bDirect(bDirect), m_iBase(iBase)
{
m_vNeiB.resize(n);
}
CNeiBo2(int n, vector<vector>& edges, bool bDirect, int iBase = 0) :m_iN(n), m_bDirect(bDirect), m_iBase(iBase)
{
m_vNeiB.resize(n);
for (const auto& v : edges)
{
m_vNeiB[v[0] - iBase].emplace_back(v[1] - iBase);
if (!bDirect)
{
m_vNeiB[v[1] - iBase].emplace_back(v[0] - iBase);
}
}
}
inline void Add(int iNode1, int iNode2)
{
iNode1 -= m_iBase;
iNode2 -= m_iBase;
m_vNeiB[iNode1].emplace_back(iNode2);
if (!m_bDirect)
{
m_vNeiB[iNode2].emplace_back(iNode1);
}
}
const int m_iN;
const bool m_bDirect;
const int m_iBase;
vector<vector> m_vNeiB;
};

class Solution {
public:
vector placedCoins(vector<vector>& edges, vector& cost) {
m_cost = cost;
m_vAns.resize(cost.size());
CNeiBo2 neiBo(cost.size(), edges, false);
multiset<int, greater> more0;
multiset less0;
DFS(more0, less0, neiBo.m_vNeiB, 0, -1);
return m_vAns;
}
void DFS(multiset<int, greater>& more0, multiset& less0, vector<vector>& neiBo, int cur, int par)
{
if (m_cost[cur] > 0)
{
more0.emplace(m_cost[cur]);
}
else
{
less0.emplace(m_cost[cur]);
}
for (const auto& next : neiBo[cur])
{
if (next == par)
{
continue;
}
multiset<int, greater> more01;
multiset less01;
DFS(more01, less01, neiBo, next, cur);
Union(more0, more01);
Union(less0, less01);
}
long long& llRet = m_vAns[cur];
if (more0.size() + less0.size() < 3)
{
llRet = 1;
return;
}
if (more0.size() >= 3)
{
auto it = more0.begin();
llRet = max(llRet, (long long)*(it++) * *(it++) * (it++));
}
if (more0.size() && (less0.size() >= 2))
{
llRet = max(llRet, (long long)
(more0.begin()) * *(less0.begin()) * *(std::next(less0.begin())));
}
};
template
void Union(T& set1, const T& set2)
{
for (const auto& n : set2)
{
set1.emplace(n);
}
while (set1.size() > 3)
{
set1.erase(prev(set1.end()));
}
}
vector m_cost;
vector m_vAns;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关

下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

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

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

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

相关文章

C++2024寒假J312实战班2.5

题目列表&#xff1a; #1多项式输出 #2龙虎斗 #3表达式求值 #4解密 #1多项式输出 这是第一个题目很简单&#xff0c;我也作对了。 我们下来看一下题目&#xff1a; 我们先来看一下样例&#xff1a; 5 100 -1 1 -3 0 10 首先100是第一项&#xff0c;所以不输出加号&…

【单片机】简单的自定义延时程序设计(代码演示)

前言 大家好吖&#xff0c;欢迎来到 YY 滴 单片机系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过单片机的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY…

突破编程_C++_面试(基础知识(11))

面试题34&#xff1a;什么是继承&#xff0c;它有哪些类型 继承是面向对象编程的一个基本概念&#xff0c;它允许一个类&#xff08;派生类、子类&#xff09;继承另一个类&#xff08;基类、父类&#xff09;的属性和方法。继承可以减少代码冗余&#xff0c;提高代码重用性&a…

【个人笔记】计算机网络五层结构理解

#纯属个人笔记 作为学习记录用途 #较多个人比较好理解的说法 可能不太准确 若发现错误 欢迎评论区指正 不希望误导小白 详细的概念请以书本的定义为准 目录 正片 传统的五层结构 如下&#xff1a; 物理层&#xff08;Physical Layer&#xff09;&#xff1a; 负责传输比特流…

C#阿里云消息列队推送消息

推送消息到队列 IMNS nativeclient new Aliyun.MNS.MNSClient(accessKeyId, accessKeySecret, endpoint, _stsToken);var nativeSend nativeclient.GetNativeTopic("SMQ");nativeSend.PublishMessage("推送消息内容"); 需要引用Aliyun.MNS.dll 下载地址…

【Linux】信号保存与信号捕捉处理

信号保存与信号捕捉 一、信号保存1. 信号的发送2. 理解信号保存&#xff08;1&#xff09;信号保存原因&#xff08;2&#xff09;信号保存概念 3. 信号保存系统接口&#xff08;1&#xff09;sigset_t&#xff08;2&#xff09;sigprocmask()&#xff08;3&#xff09;sigpend…

论文阅读-GROUP:一种聚焦于工作负载组行为的端到端多步预测方法

摘要 准确地预测工作负载可以使网络服务提供商实现应用程序的主动运行管理&#xff0c;确保服务质量和成本效益。对于云原生应用程序来说&#xff0c;多个容器协同处理用户请求&#xff0c;导致每个容器的工作负载变化受到工作负载组行为的影响。然而&#xff0c;现有方法主要…

代码随想录算法训练营第三十四天丨16.1 活动选择、877. 石子游戏

16.1 活动选择 最优子结构 活动选择问题的最优子结构意味着问题的最优解包含了其子问题的最优解。具体来说&#xff0c;如果我们有一个按结束时间排序的活动集合 S{a1​,a2​,...,an​}&#xff0c;并且 S’ 是 S 的最大兼容活动子集&#xff0c;那么对于 S′ 中的任何活动aj…

Hyper-V 调整 设置 Ubuntu 虚拟机的分辨率

使用win10 的hyper-v安装 ubuntu20&#xff0c; 在ubuntu内无法调整display settings。可以使用以下方法 解决&#xff1a; 1.修改ubuntu系统中的grub文件&#xff1b; 使用命令行&#xff1a; sudo vi /etc/default/grub 找到GRUB_CMDLINE_LINUX_DEFAULT这一行&#xff0c;…

JAVA基本内容(数据类型、标识符、数组、注释、关键字)

目录 基本数据类型 取值范围大小 情景一&#xff1a; 情景二&#xff1a; 情景三&#xff1a; 情景四&#xff1a; 标识符 情景一&#xff1a; 情景二&#xff1a; 情景三&#xff1a; 数组 一维数组 二维数组 多维数组 注释 单行注释 多行注释 文档注释 关键字 基本数据类…

【Android】使用Termux终端搭建本地web服务器

在Android手机上有一个Termux APP&#xff0c;可运行类似 Linux 终端的模拟器&#xff0c;可以运行Nodejs&#xff0c;正好用它运行本地站点&#xff0c;用不着去租服务器&#xff0c;相比运行在电脑上&#xff0c;节省了电费&#xff0c;想要学来用的话不妨看看这篇文章。 文章…

案例:CentOS8 在 MySQL8.0 实现半同步复制

异步复制 MySQL 默认的复制即是异步的&#xff0c;主库在执行完客户端提交的事务后会立即将结果返给给客户端&#xff0c;并不关心从库是否已经接收并处理&#xff0c;这样就会有一个问题&#xff0c;主节点如果 crash 掉了&#xff0c;此时主节点上已经提交的事务可能并没有传…

Python:解析获取连续的重叠对pairwise

简介&#xff1a;pairwise函数&#xff0c;返回从输入迭代器获取的重叠对的迭代器&#xff0c;是Python 3.10 新特性&#xff0c;表示一个迭代器从对象中获取连续的重叠对&#xff0c;在某些场景中可以优化代码运行效率。pairwise 函数是一种用于处理列表中元素之间配对操作的通…

四元数如何进行标准化?

假设有一个四元数的张量 r&#xff0c;它包含了两个四元数&#xff1a; r [ 1 2 3 4 4 3 2 1 ] r \begin{bmatrix} 1 & 2 & 3 & 4 \\ 4 & 3 & 2 & 1 \\ \end{bmatrix} r[14​23​32​41​] 这里&#xff0c;第一个四元数是 q 1 ( 1 , 2 , 3 , 4 ) …

【Langchain Agent研究】SalesGPT项目介绍(二)

【Langchain Agent研究】SalesGPT项目介绍&#xff08;一&#xff09;-CSDN博客 上节课&#xff0c;我们介绍了SalesGPT他的业务流程和技术架构&#xff0c;这节课&#xff0c;我们来关注一下他的项目整体结构、poetry工具和一些工程项目相关的设计。 项目整体结构介绍 我们把…

互联网医院架构系统设计与实现

随着互联网技术的快速发展&#xff0c;互联网医院作为一种新兴的医疗服务模式&#xff0c;正逐渐受到人们的关注和使用。本文将介绍互联网医院架构系统的设计原则和关键组件&#xff0c;以及如何实现一个安全、高效和可扩展的互联网医疗服务平台。 内容&#xff1a; 1. 引言 …

LeetCode Python - 9.回文数

文章目录 题目答案运行结果 题目 给你一个整数 x &#xff0c;如果 x 是一个回文整数&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 回文数是指正序&#xff08;从左向右&#xff09;和倒序&#xff08;从右向左&#xff09;读都是一样的整数。 例如&am…

【开源】基于JAVA+Vue+SpringBoot的实验室耗材管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 耗材档案模块2.2 耗材入库模块2.3 耗材出库模块2.4 耗材申请模块2.5 耗材审核模块 三、系统展示四、核心代码4.1 查询耗材品类4.2 查询资产出库清单4.3 资产出库4.4 查询入库单4.5 资产入库 五、免责说明 一、摘要 1.1…

【JavaScript】文档对象模型(DOM)的基本概念

文章目录 1. 什么是DOM2. DOM的层次结构3. 获取DOM元素通过标签名获取元素通过ID获取元素通过类名获取元素 4. 操作DOM元素修改元素内容修改元素样式添加新元素 5. 事件处理6. 总结 文档对象模型&#xff08;DOM&#xff09;是 JavaScript 中一个重要的概念&#xff0c; 它允许…

【ECMAScript modules规范示例详解——介绍】

ECMAScript modules规范示例详解——介绍 1. 介绍2. 创建一个模块&#xff08;module.js&#xff09;3. 导入模块&#xff08;main.js&#xff09;4. 说明 1. 介绍 ECMAScript 模块 (ESM) 是 JavaScript 的官方标准&#xff0c;用于在 JavaScript 应用程序中导入和导出模块&am…