图论:1857. 有向图中最大颜色值(拓扑排序+动态规划)
文章目录
- 1.问题分析
- 2.代码解析
- 2.1 代码步骤
- 1. 初始化数据结构
- 2. 构建图和入度数组
- 3. 初始化队列
- 4. 拓扑排序和动态规划
- 5. 检查是否存在环并返回结果
- 3. 问题扩展
- 1. 最长路径问题(DAG)
- 2. 最短路径问题(DAG)
- 3. 最大路径和问题
- 4. 路径计数问题
- 5. 关键路径法(Critical Path Method, CPM)
- 6. DAG上的单源最短路径(Single Source Shortest Path in DAG)
- 7. 有向无环图中的最大子序列和问题
- 8. DAG中的最长递增子序列问题
- 9. 资源分配问题(DAG)
LeetCode:1857. 有向图中最大颜色值
本题乍一看和求所有路径中的最长路径没啥区别,直接暴力枚举所有路径,但是时间复杂度不允许我们这样做。
1.问题分析
数据结构:图的拓扑排序与关键路径
其实关键路径就是使用了动态规划解法,它先将有向无环图进行拓扑排序,然后按照拓扑序进行动态规划。
- 有向无环图一定存在拓扑排序
- 按照拓扑序顺序遍历,每次更新该结点的后继,按照这个方法,遍历到某结点时一定能够保证其前驱都已经遍历过并且进行过更新。我们并不需要关心具体的顺序是什么,但一定有边 < u , v > <u,v> <u,v>, u u u的状态能够更新 v v v。
因此本题也可以使用拓扑排序+动态规划。

2.代码解析
我们定义一个 d p [ i ] [ c ] dp[i][c] dp[i][c]表示第 i i i个节点的颜色 c c c。
则必有: d p [ i ] [ c ] = m a x ( d p [ i p r e ] [ c ] ) + I ( i p r e , i ) dp[i][c] = max(dp[i_{pre}][c]) + I(i_{pre},i) dp[i][c]=max(dp[ipre][c])+I(ipre,i)
- 求到达第 i i i个节点时 能够包含的最多颜色 c c c的个数,等价于到达其前驱 i p r e i_{pre} ipre能够包含的最多颜色 c c c的个数再一步到达 i i i包含的个数。
class Solution {
public:int largestPathValue(string colors, vector<vector<int>>& edges) {vector<vector<int>> dp(colors.size(), vector<int>(26, 0));vector<int> inDegrees(colors.size(), 0);vector<vector<int>> graph(colors.size());for(int i = 0; i < edges.size(); ++i){inDegrees[edges[i][1]] ++;graph[edges[i][0]].emplace_back(edges[i][1]);}vector<int> topo;//拓扑序queue<int> q;for(int i = 0; i < colors.size(); ++ i){if(inDegrees[i] == 0){q.push(i);}}while(!q.empty()){int u = q.front(); q.pop();topo.emplace_back(u);for(auto & v : graph[u]){-- inDegrees[v];if(inDegrees[v] == 0) {q.push(v);}}}int ans = 0;for(auto & u : topo){for(int i = 0; i < 26; ++ i){if(colors[u] == 'a' + i) dp[u][i] ++;ans = max(ans, dp[u][i]);for(auto & v : graph[u]){dp[v][i] = max(dp[u][i], dp[v][i]);}}}if(topo.size() != colors.size()) return -1;return ans;}
};
可以进行进一步优化:
(1)拓扑排序的过程中更新,这样就不用求出拓扑序了,因为排序的过程中就是拓扑序了,所以边排序边更新状态。
(2)ans的求解使用 a n s = m a x ( a n s , d p [ u ] [ c o l o r s [ u ] − ′ a ′ ] ) ans = max(ans, dp[u][colors[u] - 'a']) ans=max(ans,dp[u][colors[u]−′a′]),原因在于,任何一个颜色最大路径,该颜色的最后一个结点都会被遍历到,用该结点就能求出最大值。
(3)由于是固定大小的数组,直接使用array即可。(这是加速的关键)
使用vector<int>(26, 0):

使用array<int, 26>:

这说明在不使用动态数组的情况下,固定大小的静态数组使用array比vector快很多。
class Solution {
public:int largestPathValue(string colors, vector<vector<int>>& edges) {vector<array<int, 26>> dp(colors.size());vector<int> inDegrees(colors.size(), 0);vector<vector<int>> graph(colors.size());for(int i = 0; i < edges.size(); ++i){inDegrees[edges[i][1]] ++;graph[edges[i][0]].emplace_back(edges[i][1]);}queue<int> q;for(int i = 0; i < colors.size(); ++ i){if(inDegrees[i] == 0){q.push(i);}}int ans = 0;int topo = 0;while(!q.empty()){int u = q.front(); q.pop();topo ++;dp[u][colors[u] - 'a'] ++;ans = max(ans, dp[u][colors[u] - 'a']);for(auto & v : graph[u]){-- inDegrees[v];if(inDegrees[v] == 0) {q.push(v);}for(int i = 0; i < 26; ++ i){dp[v][i] = max(dp[u][i], dp[v][i]);}}}if(topo != colors.size()) return -1;return ans;}
};
好的,让我们详细解释这段代码。该代码的目的是解决一个有向图中的最大路径值问题,其中每个节点都有一个颜色。目标是找到从图的起点到终点路径中某种颜色出现最多的次数。
2.1 代码步骤
1. 初始化数据结构
vector<array<int, 26>> dp(colors.size());
vector<int> inDegrees(colors.size(), 0);
vector<vector<int>> graph(colors.size());
dp:一个二维数组,dp[i][j]表示从起点到节点i的路径中颜色j(用0到25表示)的最大出现次数。inDegrees:记录每个节点的入度。graph:表示图的邻接表。
2. 构建图和入度数组
for(int i = 0; i < edges.size(); ++i){inDegrees[edges[i][1]]++;graph[edges[i][0]].emplace_back(edges[i][1]);
}
- 遍历
edges,填充inDegrees和graph。 - 对于每一条边
(u, v),增加v的入度,并在graph[u]中添加v。
3. 初始化队列
queue<int> q;
for(int i = 0; i < colors.size(); ++i){if(inDegrees[i] == 0){q.push(i);}
}
- 初始化一个队列
q,将所有入度为 0 的节点入队。这些节点作为拓扑排序的起点。
4. 拓扑排序和动态规划
int ans = 0;
int topo = 0;
while(!q.empty()){int u = q.front(); q.pop();topo++;dp[u][colors[u] - 'a']++;ans = max(ans, dp[u][colors[u] - 'a']);for(auto & v : graph[u]){--inDegrees[v];if(inDegrees[v] == 0) { q.push(v); }for(int i = 0; i < 26; ++i){dp[v][i] = max(dp[u][i], dp[v][i]);}}
}
ans:记录路径上颜色出现的最大次数。topo:记录拓扑排序的节点数量,用于检测是否存在环。
主要逻辑:
- 取队首节点
u,更新topo。 - 更新
dp[u][colors[u] - 'a'],表示节点u的颜色出现次数增加。 - 更新
ans为当前颜色出现的最大次数。 - 遍历
u的邻接节点v:- 减少
v的入度。 - 如果
v的入度为 0,入队q。 - 更新
dp[v],根据从u到v的路径更新v的颜色出现次数。
- 减少
5. 检查是否存在环并返回结果
if(topo != colors.size()) return -1;
return ans;
- 如果拓扑排序遍历的节点数量不等于
colors的长度,说明图中存在环,返回 -1。 - 否则,返回
ans,即路径上某种颜色的最大出现次数。
3. 问题扩展
1. 最长路径问题(DAG)
问题描述:
在一个有向无环图(DAG)中找到从一个起点到终点的最长路径。
解决方案:
- 使用拓扑排序确定处理节点的顺序。
- 按照拓扑序进行动态规划,计算每个节点的最长路径长度。
2. 最短路径问题(DAG)
问题描述:
在一个有向无环图(DAG)中找到从一个起点到终点的最短路径。
解决方案:
- 使用拓扑排序确定处理节点的顺序。
- 按照拓扑序进行动态规划,计算每个节点的最短路径长度。
3. 最大路径和问题
问题描述:
在一个有向无环图(DAG)中找到从起点到终点的路径中权重总和最大的路径。
解决方案:
- 使用拓扑排序确定处理节点的顺序。
- 按拓扑序进行动态规划,计算每个节点的路径权重总和。
4. 路径计数问题
问题描述:
计算从起始点到终点的所有可能路径的数量。
解决方案:
- 使用拓扑排序确定处理节点的顺序。
- 按拓扑序计算从起始点到每个节点的路径数量。
5. 关键路径法(Critical Path Method, CPM)
问题描述:
在项目管理中,给定一组任务及其依赖关系,找出项目的关键路径和项目的最短完成时间。
解决方案:
- 使用拓扑排序确定任务的处理顺序。
- 按拓扑序进行动态规划,计算每个任务的最早开始时间和最晚开始时间,从而确定关键路径。
6. DAG上的单源最短路径(Single Source Shortest Path in DAG)
问题描述:
在一个有向无环图(DAG)中找到从一个起点到所有其他节点的最短路径。
解决方案:
- 使用拓扑排序确定处理节点的顺序。
- 按拓扑序进行动态规划,计算从起点到每个节点的最短路径长度。
7. 有向无环图中的最大子序列和问题
问题描述:
在一个有向无环图(DAG)中找到从起点到终点的最大子序列和。
解决方案:
- 使用拓扑排序确定处理节点的顺序。
- 按拓扑序进行动态规划,计算每个节点的最大子序列和。
8. DAG中的最长递增子序列问题
问题描述:
在一个有向无环图(DAG)中找到从起点到终点的最长递增子序列。
解决方案:
- 使用拓扑排序确定处理节点的顺序。
- 按拓扑序进行动态规划,计算每个节点的最长递增子序列长度。
9. 资源分配问题(DAG)
问题描述:
在一个有向无环图(DAG)中,给定每个节点的资源需求和资源量,计算从起点到终点的最大资源分配路径。
解决方案:
- 使用拓扑排序确定处理节点的顺序。
- 按拓扑序进行动态规划,计算每个节点的最大资源分配路径。
相关文章:
图论:1857. 有向图中最大颜色值(拓扑排序+动态规划)
文章目录 1.问题分析2.代码解析2.1 代码步骤1. 初始化数据结构2. 构建图和入度数组3. 初始化队列4. 拓扑排序和动态规划5. 检查是否存在环并返回结果 3. 问题扩展1. 最长路径问题(DAG)2. 最短路径问题(DAG)3. 最大路径和问题4. 路…...
pytorch学习笔记3 tensor索引和切片
dim 0 占先 切片 (前N或者后N个) :2 表示 0到2(不包含2), 1:表示 1到末尾, -1表示最后一个元素,-2表示倒数第二个 0:28:2 表示从0到27隔点采样 :ÿ…...
学习记录——day23 多进程编程
目录 一、多进程引入 1.1、引入目的 1.2、进程的概念 1.3、进程的种类 1.4、进程号的概念 1.5、特殊进程 0号 1号 2号 孤儿 僵尸 1.6、进程的相关命令 1)查看进程信息的命令:ps 跟不同的选项,执行不同的状态 2&am…...
英特尔股市暴跌,财报亏损 | HuggingFace 实现盈利 |iOS18 Beta 苹果AI
写在前面 了解一下最近科技圈发生的一些事情 英特尔 硬件巨头英特尔宣布裁掉1.5w个岗位,约占英特尔员工的12%,非常的夸张。本次裁员可能是由于前段时间英特尔的i7,i9的13/14代处理器的暴雷,导致英特尔Q2的财报低迷。 今年以来…...
C++入门基础(二)
6. 引用(引用就是取别名) 6.1 引用的概念和定义 引用不是新定义一个变量,而是给已存在变量取了⼀个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。比如:水浒传中李逵&…...
fabricjs 实现图像的二值化功能
一、效果图 二、图像二值化的作用 二值化是图像处理中常用的一种方法,其作用是将灰度图像转换为二值图像,即将图像中的像素点根据其灰度值分成两类:黑色和白色。这种处理方法可以帮助我们更清晰地识别图像中的目标,简化图像的复杂…...
修改本地hosts文件及外部访问机器本地hosts文件后,rancher UI网站仍然不能访问
原因排查 kubectl get svc # 输出: NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d17hkubectl get svc -A # 输出: NAMESPACE …...
西北潮榆林范儿,新榆林首个360°沉浸式剧场发布会闪耀亮相
这是一场城市更迭的未来大赏,也是一场商业蝶变的复合对话 8月3日,朗阁集团商业品牌发布会在榆林银杏熙悦酒店隆重启幕。朗阁集团董事长杨志成携众多集团领导出席;多家主流媒体代表联袂参加;喜茶、中影时光国际影城、汉堡王、鲍师傅…...
如何创建响应式移动端网页设计?最佳实践详解
移动端网页设计是一个耗时而复杂的过程开发,包括UI设计、UX设计、检测、发布、改进、维护和持续的错误修复。通过学习这篇文章,你将掌握什么是移动端网页,如何制作移动端网页,以及设计网页的技巧。 什么是移动端网页?…...
Python 如何进行Web抓取(BeautifulSoup, Scrapy)
Web抓取(Web Scraping)是一种从网站提取数据的技术。Python有许多用于Web抓取的库,其中最常用的是BeautifulSoup和Scrapy。 BeautifulSoup BeautifulSoup是一个用于解析HTML和XML文档的Python库,适合处理简单的Web抓取任务。它将…...
白骑士的PyCharm教学进阶篇 2.5 数据库连接与管理
系列目录 上一篇:白骑士的PyCharm教学进阶篇 2.4 Django开发支持 在Web开发中,数据库是必不可少的部分。PyCharm不仅是一款功能强大的IDE,还提供了丰富的数据库连接和管理工具,使开发者可以更方便地浏览和操作数据库。本篇将详细…...
(五)activiti-modeler 编辑器初步优化
最终效果: 1..首先去掉顶部的logo,没什么用,还占用空间。 修改modeler.html文件,添加样式: <style type"text/css"> #main-header{display: none; } #main{padding: 0px; } </style> 2.左边组…...
(学习总结12)C++类和对象3
C类和对象3 一、初始化列表二、类型转换三、static成员四、友元五、内部类六、匿名对象 以下代码环境在 VS2022。 一、初始化列表 之前我们实现构造函数时,初始化成员变量主要使用函数体内赋值,构造函数初始化还有⼀种方式,就是初始化列表&a…...
docxtpl,一个强大的 Python 库!
更多资料获取 📚 个人网站:ipengtao.com 大家好,今天为大家分享一个强大的 Python 库 - docxtpl。 项目地址:https://docxtpl.readthedocs.io/en/latest/ 在日常工作中,自动生成和处理 Word 文档是一个常见需求。doc…...
捷途山海T2:超长续航,节能环保的驾驶新星
在当今的汽车市场中,消费者的购车选择日趋多样化,不再仅限于传统的燃油车。随着环保理念的深入人心以及人们对用车成本的日益关注,像捷途山海T2这样配备高效混动系统的车型逐渐受到大众的青睐。 捷途山海T2,以其杰出的节能性、强劲…...
[Day 45] 區塊鏈與人工智能的聯動應用:理論、技術與實踐
區塊鏈的可擴展性挑戰 概述 區塊鏈技術在過去幾年中取得了顯著的進展,其去中心化、透明和安全的特性使其在金融、供應鏈管理、醫療等領域得到了廣泛應用。然而,區塊鏈技術的一個重大挑戰是其可擴展性。可擴展性是指系統能夠有效處理日益增長的數據和用…...
白骑士的PyCharm教学实战项目篇 4.3 自动化测试与持续集成
系列目录 上一篇: 在现代软件开发过程中,自动化测试与持续集成(CI)是确保代码质量和快速交付的关键环节。PyCharm作为一款强大的集成开发环境(IDE),为自动化测试和持续集成提供了全面的支持。本…...
权限模块开发+权限与角色关联(完整CRUD)
文章目录 🌞 Sun Frame:SpringBoot 的轻量级开发框架(个人开源项目推荐)🌟 亮点功能📦 spring cloud模块概览常用工具 🔗 更多信息1.easycode生成代码1.配置2.AuthPermissionDao.java剪切到mapp…...
llama神经网络的结构,llama-3-8b.layers=32 llama-3-70b.layers=80; 2000汉字举例说明
目录 llama-3-8b.layers=32 llama-3-70b.layers=80 llama神经网络的结构 Llama神经网络结构示例 示例中的输入输出大小 实际举例说明2000个汉字文本数据集 初始化词嵌入矩阵 1. 输入层 2. 嵌入层 3. 卷积层 4. 全连接层 llama-3-8b.layers=32 llama-3-70b.laye…...
单细胞数据怎么表现genes mRNA表达的热图?
愿武艺晴小朋友一定得每天都开心 #热图 library("ComplexHeatmap") exp <- AverageExpression(subset(fasting_memory, Celltype %in% c("Pre-B")), layer = "data", #即CPM值 features …...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
