【深度优先】【图论】【C++算法】2045. 到达目的地的第二短时间

news2024/11/18 9:22:48

作者推荐

视频算法专题

LeetCode2045. 到达目的地的第二短时间

城市用一个 双向连通 图表示,图中有 n 个节点,从 1 到 n 编号(包含 1 和 n)。图中的边用一个二维整数数组 edges 表示,其中每个 edges[i] = [ui, vi] 表示一条节点 ui 和节点 vi 之间的双向连通边。每组节点对由 最多一条 边连通,顶点不存在连接到自身的边。穿过任意一条边的时间是 time 分钟。
每个节点都有一个交通信号灯,每 change 分钟改变一次,从绿色变成红色,再由红色变成绿色,循环往复。所有信号灯都 同时 改变。你可以在 任何时候 进入某个节点,但是 只能 在节点 信号灯是绿色时 才能离开。如果信号灯是 绿色 ,你 不能 在节点等待,必须离开。
第二小的值 是 严格大于 最小值的所有值中最小的值。
例如,[2, 3, 4] 中第二小的值是 3 ,而 [2, 2, 4] 中第二小的值是 4 。
给你 n、edges、time 和 change ,返回从节点 1 到节点 n 需要的 第二短时间 。
注意:
你可以 任意次 穿过任意顶点,包括 1 和 n 。
你可以假设在 启程时 ,所有信号灯刚刚变成 绿色 。
示例 1: 
输入:n = 5, edges = [[1,2],[1,3],[1,4],[3,4],[4,5]], time = 3, change = 5
输出:13
在这里插入图片描述

解释:
上面的左图展现了给出的城市交通图。
右图中的蓝色路径是最短时间路径。
花费的时间是:

  • 从节点 1 开始,总花费时间=0
  • 1 -> 4:3 分钟,总花费时间=3
  • 4 -> 5:3 分钟,总花费时间=6
    因此需要的最小时间是 6 分钟。
    右图中的红色路径是第二短时间路径。
  • 从节点 1 开始,总花费时间=0
  • 1 -> 3:3 分钟,总花费时间=3
  • 3 -> 4:3 分钟,总花费时间=6
  • 在节点 4 等待 4 分钟,总花费时间=10
  • 4 -> 5:3 分钟,总花费时间=13
    因此第二短时间是 13 分钟。
    示例 2:
    输入:n = 2, edges = [[1,2]], time = 3, change = 2
    输出:11
    解释:
    最短时间路径是 1 -> 2 ,总花费时间 = 3 分钟
    第二短时间路径是 1 -> 2 -> 1 -> 2 ,总花费时间 = 11 分钟

提示:

2 <= n <= 104
n - 1 <= edges.length <= min(2 * 104, n * (n - 1) / 2)
edges[i].length == 2
1 <= ui, vi <= n
ui != vi
不含重复边
每个节点都可以从其他节点直接或者间接到达
1 <= time, change <= 103

深度优先

经过的边数相同,则行驶时间相同,等待时间也相同。所以本题等效与求严格经过边数第二少。令经过最少的边数是x,则严格第二少的边数只能是x+1或x+2。因为:到达目的地后返回一个节点,再到达目的地,经过的边数是x+2。
本问题等于与:
一,计算最少经过边数x。
二,能否经过x+1条边到达目的的。

每个节点除了记录最少边数,还要记录另外一个状态i1:
初始为0,第一次到达是变成1。加入队列。
1变2的条件:新经过的边数等于x+1。加入队列。
2不会发生的变化。
每个节点最多入队两次。估计时间复杂度是:O(n)。
目的地的i1,如果为1,则严格第二少的边数为x+1,否则为x+2。

通过边数计算时间:
如果总时间time / change 是奇数需要等待 等待时间 change - (time/change)。

代码

核心代码

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:
	int secondMinimum(int n, vector<vector<int>>& edges, int time, int change) {
		CNeiBo2 neiBo(n, edges, false, 1);
		queue<pair<int,int>> que;		
		vector<int> vDis(n), vStatu(n);
		que.emplace(0,0);
		vStatu[0] = 1;
		while (que.size())
		{
			const auto [cur,curDis] = que.front();
			que.pop();
			for (const auto& next : neiBo.m_vNeiB[cur])
			{
				const int iNewDis = curDis + 1;
				if (0 == vStatu[next])
				{
					vDis[next] = iNewDis;
					vStatu[next] = 1;
					que.emplace(next,iNewDis);
				}
				else if ((1 == vStatu[next])&&( vDis[next]+1 == iNewDis))
				{
					vStatu[next] = 2;
					que.emplace(next, iNewDis);
				}
			}
		}
		const int iEdgeNum = (1 == vStatu.back()) ? (vDis.back() + 2) : (vDis.back() + 1);
		int iTime = 0;
		for (int i = 1; i <= iEdgeNum; i++)
		{
			iTime += time;
			if ((iTime / change) & 1)
			{
				if (iEdgeNum != i)
				{
					iTime += (change - (iTime % change));
				}
			}
		}
		return iTime;
	}
};

测试用例

template<class T,class T2>
void Assert(const T& t1, const T2& t2)
{
assert(t1 == t2);
}

template
void Assert(const vector& v1, const vector& v2)
{
if (v1.size() != v2.size())
{
assert(false);
return;
}
for (int i = 0; i < v1.size(); i++)
{
Assert(v1[i], v2[i]);
}

}

int main()
{
int n, time, change;
vector<vector> edges;
{
Solution sln;
n = 5, edges = { {1,2},{1,3},{1,4},{3,4},{4,5} }, time = 3, change = 5;
auto res = sln.secondMinimum(n, edges, time, change);
Assert(13, res);
}
{
Solution sln;
n = 2, edges = { {1,2} }, time = 3, change = 2;
auto res = sln.secondMinimum(n, edges, time, change);
Assert(11, res);
}
}

2023年4月

class Solution {
public:
int secondMinimum(int n, vector<vector>& edges, int time, int change) {
m_vNeiB.resize(n + 1);
m_vDis.assign(n + 1,INT_MAX);
m_vDis2.assign(n + 1, INT_MAX);
for (const auto& e : edges)
{
m_vNeiB[e[0]].emplace_back(e[1]);
m_vNeiB[e[1]].emplace_back(e[0]);
}
std::queue<pair<int,int>> que;
que.emplace(1,0);
while (que.size())
{
const int iCur = que.front().first;
const int len = que.front().second;
que.pop();
for (const auto& next : m_vNeiB[iCur])
{
const int iNewLen = len + 1;
if (iNewLen >= m_vDis2[next])
{
continue;
}
que.emplace(next, iNewLen);
if (iNewLen < m_vDis[next])
{
m_vDis[next] = iNewLen;
}
else if (iNewLen != m_vDis[next])
{
m_vDis2[next] = iNewLen;
}
}
}
int tmp = m_vDis2[n];
int iRet = 0;
while (tmp–)
{
if ((iRet / change) & 1)
{
iRet += (change - iRet%change);
}
iRet += time;
}
return iRet;
}
vector<vector> m_vNeiB;
vector m_vDis;
vector m_vDis2;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步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.coloradmin.cn/o/1499096.html

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

相关文章

开源分子对接程序rDock使用方法(1)-Docking in 3 steps

欢迎浏览我的CSND博客&#xff01; Blockbuater_drug …点击进入 文章目录 前言一、Docking in 3 steps 标准对接rDock 的基本对接步骤及注意事项 二、 三步对接案例Step 1. 结构文件准备Step 2. 产生对接位点Step 3. 运行分子对接3.1 检查输入文件3.2 测试-只进行打分3.3 运行…

Linux/Validation

Enumeration nmap 第一次扫描发现系统对外开放了22&#xff0c;80&#xff0c;4566和8080端口&#xff0c;端口详细信息如下 系统对外开放了4个端口&#xff0c;从nmap的结果来看&#xff0c;8080无法访问&#xff0c;手动尝试后4566也无法访问&#xff0c;只能从80端口开始 …

用MATLAB求解微分方程

第一篇为 基础概念 &#xff0c;第二篇为 R-K法的具体实现方法。 &#xff08;一&#xff09;常微分方程的MATLAB求解 概要&#xff1a; 常微分方程的MATLAB求解分为解析解、数值解解析解(只有少数微分方程组有解析解)&#xff1a;dsolve函数数值解&#xff1a;solver函数&a…

Python实例☞数据类型及运算符案例

实例一&#xff1a; ❶要求☞从键盘获取一个4位整数&#xff0c;并分别输出个、十、百、千位 ❷程序代码☞ ①第一种方法 print(请输入一个4位整数&#xff1a;) xeval(input()) print(个位数为&#xff1a;,x%10) print(十位数为&#xff1a;,(x//10)%10) print(百位数为&am…

Transformer中的FeedForward

Transformer中的FeedForward flyfish class PoswiseFeedForwardNet(nn.Module):def __init__(self, d_ff2048):super(PoswiseFeedForwardNet, self).__init__()# 定义一维卷积层 1&#xff0c;用于将输入映射到更高维度self.conv1 nn.Conv1d(in_channelsd_embedding, out_ch…

自律篇001-养成自律的秘密武器1-目标规划表

&#x1f680;以前在某书上看到一些博主非常自律&#xff0c;比如每天5点多起床看书&#xff0c;或者每天坚持健身&#xff0c;直到练出马甲线&#xff0c;还有一边工作一边考研等等&#xff0c;自己也曾尝试过做一些目标规划&#xff0c;但结果都不尽人意。写计划的时候往往信…

EVE-NG桥接虚拟网卡实现与虚拟机通讯

一、知识补充 1、VMware网络连接 在VM中&#xff0c;给我们提供了以下几种连接网络的模式 桥接模式&#xff1a;直接联机物理网络NAT模式&#xff1a;用于共享主机的IP地址仅主机模式&#xff1a;与主机共享的专用网络自定义&#xff1a;特定虚拟网络LAN区段 特别注意的是&am…

c++ 11 新特性 元组

一.元组介绍 C11引入了元组&#xff08;tuple&#xff09;这一新特性&#xff0c;它是一种可以存储不同类型元素的复合类型。元组类似于结构体&#xff0c;但更加灵活&#xff0c;因为它可以在运行时动态地创建和访问元素。 二.元组使用场景 C11中引入的元组&#xff08;tuple&…

css clip-path polygon属性实现直角梯形

2024.3.8今天我学习了如何用css实现直角梯形的效果&#xff0c; 效果&#xff1a; 具体实现原理&#xff1a; 一、需要三个div&#xff1a; 外面一个大的div&#xff0c;里面左右两个小的div 我们需要先把第一个div变成直角梯形&#xff1a; 大概是这样&#xff0c;设置好之…

ORA/GSA -- 学习记录

brief over-representation analysis(ORA),过表“达”分析&#xff0c;就是我们做多分组的RNAseq数据解析后会得到一些差异表达的gene&#xff0c;有些时候是单独拿出一个差异gene去解释表型&#xff0c;缺点是欠缺证据力度。有些人就把一些相关的差异gene放在一块儿解释&…

Extend继承

继承的作用 当我们定义了一个Person类&#xff1a; class Person{private Stirng name;private int age;public String getName(){....}public int getAge(){...}public void setName(String name){...}public void setAge(int age){...} }现在&#xff0c;假设还需要定义一个…

最小二乘法(带你 原理 实践)

文章目录 引言一、最小二乘法的基本原理二、最小二乘法的计算过程建立模型确定目标函数求解模型参数模型检验 三、最小二乘法的优缺点优点原理简单易懂统计特性优良适用范围广泛 缺点对异常值敏感假设条件较多 四、最小二乘法在实际应用中的案例五、如何克服最小二乘法的局限性…

OPCUA 学习笔记:程序模型

无论是边缘控制器&#xff0c;还是PLC 中&#xff0c;除了信息模型之外&#xff0c;还有应用程序&#xff0c;这些程序可能是IEC61131-3 编写的程序&#xff0c;也可能是其它程序开发的可执行程序。 尽管OPCUA 描述模型能力很强&#xff0c;但是它缺乏算法的描述方式。但是OPCU…

在k8s上部署dolphinscheduler

&#xff08;作者&#xff1a;陈玓玏&#xff09; 一、 前提条件 已部署k8s&#xff0c;版本信息如下&#xff1a; k8s为单机部署&#xff1b;已部署nfs&#xff0c;版本如下&#xff1b; 二、 部署helm 以下步骤安装的是二进制版本&#xff0c;如果通过脚本安装&#…

【AI视野·今日Sound 声学论文速览 第五十四期】Thu, 7 Mar 2024

AI视野今日CS.Sound 声学论文速览 Thu, 7 Mar 2024 Totally 8 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Sound Papers Can Audio Reveal Music Performance Difficulty? Insights from the Piano Syllabus Dataset Authors Pedro Ramoneda, Minhee Lee, Dasa…

学生信息管理APP

设计内容简介 本次设计使用Android Studio实现一个学生信息管理系统,系统功能结构如下图所示: 详细设计 数据库设计SQLite,是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低。…

Android14音频进阶:AudioTrack与AudioFlinger创建数据通道(五十八)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

UNIAPP微信小程序中使用Base64编解码原理分析和算法实现

为何要加上UNIAPP及微信小程序&#xff0c;可能是想让检索的翻围更广把。&#x1f607; Base64的JS原生编解码在uni的JS引擎中并不能直接使用&#xff0c;因此需要手写一个原生的Base64编解码器。正好项目中遇到此问题&#xff0c;需要通过URLLink进行小程序跳转并携带Base64参…

定时执行专家V7.1 多国语言版本英文版发布 - TimingExecutor V7.1 English Version Release

目录 ◆ About TimingExecutor ◆ Main Frame ◆ Job Dailog ◆ Trigger Dialog ◆ Setting Dialog ◆ About Dialog ◆ Job Detail Information panel ◆ Statistics Information panel ◆ About TimingExecutor 《定时执行专家》是一款制作精良、功能强大、毫秒精度…

数据库RDBMS1

配置MySQL 准备网络yum源&#xff08;准备物理机或一台虚拟机作为仓库服务器&#xff09; [rootzzgrhel8 ~]# yum install -y httpd php php-mysqlnd php-xml php-json createrepo [rootzzgrhel8 ~]# systemctl start httpd [rootzzgrhel8 ~]# systemctl enable httpd [root…