当前位置: 首页 > news >正文

图论: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>
在这里插入图片描述
这说明在不使用动态数组的情况下,固定大小的静态数组使用arrayvector快很多。

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,填充 inDegreesgraph
  • 对于每一条边 (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],根据从 uv 的路径更新 v 的颜色出现次数。

5. 检查是否存在环并返回结果

if(topo != colors.size()) return -1;
return ans;
  • 如果拓扑排序遍历的节点数量不等于 colors 的长度,说明图中存在环,返回 -1。
  • 否则,返回 ans,即路径上某种颜色的最大出现次数。

3. 问题扩展

1. 最长路径问题(DAG)

问题描述
在一个有向无环图(DAG)中找到从一个起点到终点的最长路径。

解决方案

  1. 使用拓扑排序确定处理节点的顺序。
  2. 按照拓扑序进行动态规划,计算每个节点的最长路径长度。

2. 最短路径问题(DAG)

问题描述
在一个有向无环图(DAG)中找到从一个起点到终点的最短路径。

解决方案

  1. 使用拓扑排序确定处理节点的顺序。
  2. 按照拓扑序进行动态规划,计算每个节点的最短路径长度。

3. 最大路径和问题

问题描述
在一个有向无环图(DAG)中找到从起点到终点的路径中权重总和最大的路径。

解决方案

  1. 使用拓扑排序确定处理节点的顺序。
  2. 按拓扑序进行动态规划,计算每个节点的路径权重总和。

4. 路径计数问题

问题描述
计算从起始点到终点的所有可能路径的数量。

解决方案

  1. 使用拓扑排序确定处理节点的顺序。
  2. 按拓扑序计算从起始点到每个节点的路径数量。

5. 关键路径法(Critical Path Method, CPM)

问题描述
在项目管理中,给定一组任务及其依赖关系,找出项目的关键路径和项目的最短完成时间。

解决方案

  1. 使用拓扑排序确定任务的处理顺序。
  2. 按拓扑序进行动态规划,计算每个任务的最早开始时间和最晚开始时间,从而确定关键路径。

6. DAG上的单源最短路径(Single Source Shortest Path in DAG)

问题描述
在一个有向无环图(DAG)中找到从一个起点到所有其他节点的最短路径。

解决方案

  1. 使用拓扑排序确定处理节点的顺序。
  2. 按拓扑序进行动态规划,计算从起点到每个节点的最短路径长度。

7. 有向无环图中的最大子序列和问题

问题描述
在一个有向无环图(DAG)中找到从起点到终点的最大子序列和。

解决方案

  1. 使用拓扑排序确定处理节点的顺序。
  2. 按拓扑序进行动态规划,计算每个节点的最大子序列和。

8. DAG中的最长递增子序列问题

问题描述
在一个有向无环图(DAG)中找到从起点到终点的最长递增子序列。

解决方案

  1. 使用拓扑排序确定处理节点的顺序。
  2. 按拓扑序进行动态规划,计算每个节点的最长递增子序列长度。

9. 资源分配问题(DAG)

问题描述
在一个有向无环图(DAG)中,给定每个节点的资源需求和资源量,计算从起点到终点的最大资源分配路径。

解决方案

  1. 使用拓扑排序确定处理节点的顺序。
  2. 按拓扑序进行动态规划,计算每个节点的最大资源分配路径。

相关文章:

图论:1857. 有向图中最大颜色值(拓扑排序+动态规划)

文章目录 1.问题分析2.代码解析2.1 代码步骤1. 初始化数据结构2. 构建图和入度数组3. 初始化队列4. 拓扑排序和动态规划5. 检查是否存在环并返回结果 3. 问题扩展1. 最长路径问题&#xff08;DAG&#xff09;2. 最短路径问题&#xff08;DAG&#xff09;3. 最大路径和问题4. 路…...

pytorch学习笔记3 tensor索引和切片

dim 0 占先 切片 &#xff08;前N或者后N个&#xff09; &#xff1a;2 表示 0到2&#xff08;不包含2&#xff09;&#xff0c; 1&#xff1a;表示 1到末尾&#xff0c; -1表示最后一个元素&#xff0c;-2表示倒数第二个 0:28:2 表示从0到27隔点采样 &#xff1a;&#xff…...

学习记录——day23 多进程编程

目录 一、多进程引入 1.1、引入目的 1.2、进程的概念 1.3、进程的种类 1.4、进程号的概念 1.5、特殊进程 0号 1号 2号 孤儿 僵尸 1.6、进程的相关命令 1&#xff09;查看进程信息的命令&#xff1a;ps 跟不同的选项&#xff0c;执行不同的状态 2&am…...

英特尔股市暴跌,财报亏损 | HuggingFace 实现盈利 |iOS18 Beta 苹果AI

写在前面 了解一下最近科技圈发生的一些事情 英特尔 硬件巨头英特尔宣布裁掉1.5w个岗位&#xff0c;约占英特尔员工的12%&#xff0c;非常的夸张。本次裁员可能是由于前段时间英特尔的i7&#xff0c;i9的13/14代处理器的暴雷&#xff0c;导致英特尔Q2的财报低迷。 今年以来…...

C++入门基础(二)

6. 引用&#xff08;引用就是取别名&#xff09; 6.1 引用的概念和定义 引用不是新定义一个变量&#xff0c;而是给已存在变量取了⼀个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间。比如&#xff1a;水浒传中李逵&…...

fabricjs 实现图像的二值化功能

一、效果图 二、图像二值化的作用 二值化是图像处理中常用的一种方法&#xff0c;其作用是将灰度图像转换为二值图像&#xff0c;即将图像中的像素点根据其灰度值分成两类&#xff1a;黑色和白色。这种处理方法可以帮助我们更清晰地识别图像中的目标&#xff0c;简化图像的复杂…...

修改本地hosts文件及外部访问机器本地hosts文件后,rancher UI网站仍然不能访问

原因排查 kubectl get svc # 输出&#xff1a; NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d17hkubectl get svc -A # 输出&#xff1a; NAMESPACE …...

西北潮榆林范儿,新榆林首个360°沉浸式剧场发布会闪耀亮相

这是一场城市更迭的未来大赏&#xff0c;也是一场商业蝶变的复合对话 8月3日&#xff0c;朗阁集团商业品牌发布会在榆林银杏熙悦酒店隆重启幕。朗阁集团董事长杨志成携众多集团领导出席&#xff1b;多家主流媒体代表联袂参加&#xff1b;喜茶、中影时光国际影城、汉堡王、鲍师傅…...

如何创建响应式移动端网页设计?最佳实践详解

移动端网页设计是一个耗时而复杂的过程开发&#xff0c;包括UI设计、UX设计、检测、发布、改进、维护和持续的错误修复。通过学习这篇文章&#xff0c;你将掌握什么是移动端网页&#xff0c;如何制作移动端网页&#xff0c;以及设计网页的技巧。 什么是移动端网页&#xff1f;…...

Python 如何进行Web抓取(BeautifulSoup, Scrapy)

Web抓取&#xff08;Web Scraping&#xff09;是一种从网站提取数据的技术。Python有许多用于Web抓取的库&#xff0c;其中最常用的是BeautifulSoup和Scrapy。 BeautifulSoup BeautifulSoup是一个用于解析HTML和XML文档的Python库&#xff0c;适合处理简单的Web抓取任务。它将…...

白骑士的PyCharm教学进阶篇 2.5 数据库连接与管理

系列目录 上一篇&#xff1a;白骑士的PyCharm教学进阶篇 2.4 Django开发支持 在Web开发中&#xff0c;数据库是必不可少的部分。PyCharm不仅是一款功能强大的IDE&#xff0c;还提供了丰富的数据库连接和管理工具&#xff0c;使开发者可以更方便地浏览和操作数据库。本篇将详细…...

(五)activiti-modeler 编辑器初步优化

最终效果&#xff1a; 1..首先去掉顶部的logo&#xff0c;没什么用&#xff0c;还占用空间。 修改modeler.html文件&#xff0c;添加样式&#xff1a; <style type"text/css"> #main-header{display: none; } #main{padding: 0px; } </style> 2.左边组…...

(学习总结12)C++类和对象3

C类和对象3 一、初始化列表二、类型转换三、static成员四、友元五、内部类六、匿名对象 以下代码环境在 VS2022。 一、初始化列表 之前我们实现构造函数时&#xff0c;初始化成员变量主要使用函数体内赋值&#xff0c;构造函数初始化还有⼀种方式&#xff0c;就是初始化列表&a…...

docxtpl,一个强大的 Python 库!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个强大的 Python 库 - docxtpl。 项目地址&#xff1a;https://docxtpl.readthedocs.io/en/latest/ 在日常工作中&#xff0c;自动生成和处理 Word 文档是一个常见需求。doc…...

捷途山海T2:超长续航,节能环保的驾驶新星

在当今的汽车市场中&#xff0c;消费者的购车选择日趋多样化&#xff0c;不再仅限于传统的燃油车。随着环保理念的深入人心以及人们对用车成本的日益关注&#xff0c;像捷途山海T2这样配备高效混动系统的车型逐渐受到大众的青睐。 捷途山海T2&#xff0c;以其杰出的节能性、强劲…...

[Day 45] 區塊鏈與人工智能的聯動應用:理論、技術與實踐

區塊鏈的可擴展性挑戰 概述 區塊鏈技術在過去幾年中取得了顯著的進展&#xff0c;其去中心化、透明和安全的特性使其在金融、供應鏈管理、醫療等領域得到了廣泛應用。然而&#xff0c;區塊鏈技術的一個重大挑戰是其可擴展性。可擴展性是指系統能夠有效處理日益增長的數據和用…...

白骑士的PyCharm教学实战项目篇 4.3 自动化测试与持续集成

系列目录 上一篇&#xff1a; 在现代软件开发过程中&#xff0c;自动化测试与持续集成&#xff08;CI&#xff09;是确保代码质量和快速交付的关键环节。PyCharm作为一款强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;为自动化测试和持续集成提供了全面的支持。本…...

权限模块开发+权限与角色关联(完整CRUD)

文章目录 &#x1f31e; Sun Frame&#xff1a;SpringBoot 的轻量级开发框架&#xff08;个人开源项目推荐&#xff09;&#x1f31f; 亮点功能&#x1f4e6; spring cloud模块概览常用工具 &#x1f517; 更多信息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中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...