基于 Dijkstra 最短路算法实现的次短路算法

次短路(第二最短路径) 第二最短路径 有句古话叫“不破不立”,这个思想跟次短路也就是第二最短路的思想一样。 算法思想:计算原图的最短路,并保存路径。一一破坏最短路中的每一条边,重新计算最短路,并排序。最小的那个就是第二最短路。 1.用dijkstra计算u->v的最短路径,保存路径上的每条边 2.依次删除最短路径上的每一条边(每次删一条),重新计算新的u->v最短路径(新的最短路>=原最短路) 3.把所有新 阅读详情

一、概述

次短路算法是指除了最短路之外长度最小的路径,一般来说在一个图中,最短路和次短路可以同时被一个最短路算法求出。
本文侧重于介绍如何在堆优化版的 Dijkstra 算法中加入次短路算法计算的方法,从而实现同时计算最短路和次短路的功能。由于对优化版的 Dijkstra 算法的时间复杂度为 O ( ( n + m ) log ⁡ m ) O((n+m)\log m) O((n+m)logm) ,所以这个算法的时间复杂度将是最短路的时间复杂度的一个常数倍数,也就是 O ( k ( n + m ) log ⁡ m )   ( k ∈ N + , k ≥ 1 ) O(k(n+m)\log m)\text{ }(k\in\mathbb{N^+},k\ge 1) O(k(n+m)logm) (k∈N+,k≥1) 。
次短路算法可以用于计算最短路算法之外的次优策略,需要时应该根据题目的条件来进行判断与分析。

二、具体实现方法

前置知识: Dijkstra 算法的具体实现步骤可以参考 这篇文章 ,本文要求读者对 Dijkstra 算法完全掌握。

首先,我们按照 Dijkstra 算法的步骤先定义一个优先队列(priority_queue) ,用来存放三个目标值:最短路的长度,当前节点的编号,以及当前的值是最短路还是次短路。三个值的类型分别是:整数,整数,布尔型。
代码实例如下,我们先定义一个结构体和一个运算符,用来存储所有的信息。(注意, priority_queue 自带的是一个小根堆,需要手动重载 < 运算符来进行排序,否则会出现意想不到的问题)。

struct Node
{
	int to, dis, ty; 
	// 这里, to 表示当前的节点编号
    //  dis 表示当前的最短路、次短路距离的值
    // ty 表示当前的值是最短路还是次短路,用 0 或者 1 表示,比如 0 表示最短路, 1 表示次短路等
	
	bool operator<(Node t) const // 这个 const 一定要加,记住即可
	{
		return dis > t.dis; // 这里是用小于符号来替代大于符号,方便 priority_queue 的定义
	}
};
priority_queue<Node> q;  // 这里已经重载了 < 运算符,所以小根堆默认按照我们给定的算法排序

然后,我们开始 Dijkstra 次短路算法的正式部分。
开始之前,我们要定义一些状态和变量。设 d ( x , 0 ) d(x,0) d(x,0) 表示从源点到 x x x 的最短路, d ( x , 1 ) d(x,1) d(x,1) 表示从源点到 y y y 的最短路, e e e 是一个向量矩阵,表示使用 vector<pair<int, int> 存储的给定的图。具体如下:

typedef pair<int, int> pii;
#define wi first
#define to second

const int N = 1e5 + 10; // 根据实际情况自己调整

int d[N][2]; // 含义如上
vector<pii> e[N]; // 使用上面构建的内容存图

初始化:首先设源点为 s s s ,将源点入队:

q.push({s, 0, 0});

然后,初始化 d d d 状态的值为 int 范围内的 ∞ \infty ∞ ,然后令 d ( s , 0 ) = 0 d(s,0)=0 d(s,0)=0 。

memset(d, 0x3f, sizeof(d));
d[s][0] = 0;

开始算法的计算部分:使用 while 循环,每次从队列中取出当前最小的值,并将当前的最小值扩展到邻近的所有点,并更新他们的最小值。如果一个点被当前点成功更新了最小值,则更新当前点的最小值和次小值。具体操作:先将次小值设置为原来的最小值,再将最小值更新为当前找到的值。简单说明如下:
设当前放入并即将更新的值为 t t t 。假设 t < d ( x , 0 ) t<d(x,0) t<d(x,0) ,则我们需要将 d ( x , 0 ) d(x,0) d(x,0) 更新成 t t t 。由于此时 t < d ( x , 0 ) , d ( x , 0 ) < d ( x , 1 ) t<d(x,0),d(x,0)<d(x,1) t<d(x,0),d(x,0)<d(x,1) ,所以我们的次小值将更新成原来的 d ( x , 0 ) d(x,0) d(x,0) 。但因为更新后的 d ( x , 0 ) = t d(x,0)=t d(x,0)=t ,所以我们需要提前件 d ( x , 1 ) = d ( x , 0 ) d(x,1)=d(x,0) d(x,1)=d(x,0) ,这样来进行变换。
此处, d ( x , 0 ) d(x,0) d(x,0) 和 d ( x , 1 ) d(x,1) d(x,1) 的计算方法 Dijkstra 算法相同,即设当前的点为 x x x ,之前访问的点为 p p p ,则状态转移方程如下:
d ( x , 0 ) = min ⁡ ∀ p , x → , x , p ∈ e { d ( p , 0 ) + p , x → } { d ( x , 1 ) = min ⁡ ∀ p , x → , x , p ∈ e { d ( p , 1 ) + p , x → } [if  d ( p , 0 ) + p , x → > d ( x , 0 ) ] d ( x , 1 ) = min ⁡ ∀ p , x → , x , p ∈ e { d ( p , 0 ) + p , x → } [if  d ( p , 0 ) + p , x → < d ( x , 0 ) ] d(x,0)=\min_{\forall \overrightarrow{p,x},x,p\in e}\{d(p,0)+\overrightarrow{p,x}\} \\ \begin{cases} d(x,1)&=\min_{\forall\overrightarrow{p,x},x,p\in e}\{d(p,1)+\overrightarrow{p,x}\} &\text{[if }d(p,0)+\overrightarrow{p,x}>d(x,0)]\\ d(x,1)&=\min_{\forall\overrightarrow{p,x},x,p\in e}\{d(p,0)+\overrightarrow{p,x}\} &\text{[if }d(p,0)+\overrightarrow{p,x}<d(x,0)] \end{cases} d(x,0)=∀p,x ​,x,p∈emin​{d(p,0)+p,x ​}{d(x,1)d(x,1)​=min∀p,x ​,x,p∈e​{d(p,1)+p,x ​}=min∀p,x ​,x,p∈e​{d(p,0)+p,x ​}​[if d(p,0)+p,x ​>d(x,0)][if d(p,0)+p,x ​<d(x,0)]​

最后,将更新后的最小值和次小值入队更新其他的点。如果一个点被当前点成功更新的次小值,则更新当前点的次小值,直接改变次小值即可,无需复杂的操作步骤。这样,我们就成功设置了一个最小值和次小值的计算过程。

// 使用 Dijkstra 算法计算最短路和次短路
while (!q.empty())
{
	Node t = q.top();
	q.pop();

	for (pii i : e[t])
	{
		if (d[i.to][0] > t.dis + i.wi)
		{
			d[i.to][1] = d[i.to][0]; // 先更新次小值,以免最小值被覆盖
			q.push({i.to, d[i.to][1], 1});
			
			d[i.to][0] = t.dis + i.wi; // 更新最小值
			q.push({i.to, d[i.to][0], 0});
		}
		else if (d[i.to][1] > t.dis + i.wi)
		{
			d[i.to][1] = t.dis + i.wi; // 更新次小值即可
			q.push({i.to, d[i.to][1], 1});
		}
	}
}

三、完整代码实现

这样,我们就实现了计算最短路和次短路的算法。代码如下,可自行添加输出答案的部分:

#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> pii;
#define wi first
#define to second
	
const int N = 1e5 + 10;

struct Node
{
	int to, dis, ty; 
	
	bool operator<(Node t) const 
	{
		return dis > t.dis;
	}
};
priority_queue<Node> q;

int d[N][2]; 
vector<pii> e[N]; 
int n, m, s;

void print()
{
	// ...
}

int main()
{
    cin >> n >> m;
    for (int i = 1, a, b, c; i <= m; ++i)
    {
    	cin >> a >> b >> c;
		
		e[a].push_back({c, b});
		e[b].push_back({c, a});
    }
    cin >> s;
	
	q.push({s, 0, 0});
	memset(d, 0x3f, sizeof(d));
	d[s][0] = 0;
	
	while (!q.empty())
	{
		Node t = q.top();
		q.pop();
	
		for (pii i : e[t])
		{
			if (d[i.to][0] > t.dis + i.wi)
			{
				d[i.to][1] = d[i.to][0]; 
				q.push({i.to, d[i.to][1], 1});
				
				d[i.to][0] = t.dis + i.wi;
				q.push({i.to, d[i.to][0], 0});
			}
			else if (d[i.to][1] > t.dis + i.wi)
			{
				d[i.to][1] = t.dis + i.wi; 
				q.push({i.to, d[i.to][1], 1});
			}
		}
	}
	
	print();
    
	return 0;
}
dijkstra求次短路(易理解) 步骤 1.找起点到每个点的最短路并用dis1数组记下来; 2.找终点到每个点的最短路并用dis2数组记下来; 3.访问每条边(如果为无向图需要遍历给的边数*2),用u表示这条边的起点,v表示这条边的终点,w表示权值,用k记下起点到u的最短路加上v到终点的最短路再加上w; 4.比较k和dis1[ t ]的大小,如果k > dis1[ t ],就与ans比较,如果小于ans,则更新ans的值为k; 5.次短路就为ans; 代码: #include<iostream> #include<a 阅读详情

相关推荐

【综合笔试题】难度 4.5/5,经典次短路问题

这是我们「刷穿 LeetCode」系列文章的第No.2045篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。

BASK2311的博客 195

次短路(两种方式) && 第K短路

次短路算法: 有两种比较简单实现次短路的思想 方法一:用 dijkstra 算法 从起点开始 同时维护 【最短路数组(dis1[ ])】 和 【次短路 数组 (dis2[ ])】 方法二:还是用到dijkstra 算法 分别用两个 dis1[ ] 数组 和 dis2[ ] 数组 分别 维护 从起点 和 从终点开始 的 最短路 ——然后枚举 所有边 , 将边的两个端点 连上 起点和终点 看是...

我歌月徘徊,我舞影零乱 5872

图论次短路算法:从Dijkstra状态扩展到网络路由应用

在图论与网络优化中,最短路径算法是解决资源最优分配问题的核心基础,Dijkstra算法通过贪心策略高效求解单源最短路径,广泛应用于路由协议与导航系统。其原理在于维护节点距离估计,通过松弛操作逐步收敛至最优解。这一技术价值在于为网络流量调度、物流规划等场景提供了确定性最优解。然而,现实系统对容错性与鲁棒性有更高要求,当主路径失效时,需要快速切换至备用路径,这引出了对次优路径的搜索需求。次短路问题正是对此的建模,其中严格次短路要求路径长度严格大于最短路且路径不同,而非严格次短路则允许长度相等但路径不同。解决严格

weixin_29611239的博客 370

次短路

次短路:大于最短路的最小路径; 最短路:求法很多,不说了 最短路计数:计算最短路的数量,以dijstra算法解最短路来说,多开一个计数的数组num[N],当我们跟新某一个点时,dis[u]>dis[v]+e[u][v] (u点与v点有路),更新num[u]=num[v]; 如果dis[u]=dis[v]+e[u][v],那就单独更新数量:num[u]+=num[v]; 次短路算法:在...

PL博客 3658

AI Agent + 大数据 + RAG:电商用户行为分析的低成本落地

本文探讨了AIAgent与大数据技术在电商用户行为分析中的应用。通过构建"数据采集-实时分析-智能决策"的全自治链路,解决了传统大数据分析的三大痛点:人工建模周期长、实时性不足和决策闭环断裂。系统采用Flink+Spark处理实时数据,结合基于DeepSeek-V3.1的AIAgent实现智能分析,并通过飞书RAG模块动态获取业务知识。落地效果显示,分析响应时间从2-3天缩短至30秒,推荐转化率提升134%,验证了该方案在提升电商数据决策效率方面的显著价值。

想~ai抽 1618

无人机室内悬停如何稳?光流与IMU数据融合实战解析

在无GPS的室内环境中,无人机自主悬停依赖多传感器融合,其中光流与IMU是核心组合。光流传感器通过图像像素位移估算相对地面的速度,长期无漂移,但易受光照和纹理影响;IMU高频响应出色,却存在积分累积漂移。两者在频率与误差特性上天然互补,融合后可实现高精度位置估计。工程实践中,需合理选型、正确处理坐标变换与时间对齐,并通过互补滤波或扩展卡尔曼滤波将光流速度修正引入状态估计,进而支撑位置环与速度环控制。这一技术不仅解决室内定点悬停,也为视觉惯性里程计等更复杂的自主定位提供基础。本文结合真实调试案例,梳理从硬件安

weixin_33314040的博客 293

严格次短路,Dijkstra——POJ - 3255

题目链接 题目含义 一个人想去朋友家,最短路不走,想走次短路,而且长度严格小于最短路 题目分析 次短路的模板题,还是挺简单的 但是与求最短路不同 Dijstra算法里此时队列中dis最小的点的dis即是它的最短路,就将它出队处理接下来的点就行了 而求次短路时,如果这个点像求最短路一样出队的话,万一这个点的次短路没求好 那完了,你已经出队了 而且,你队列里装的dis不是指...

weixin_30732487的博客 492

OpenCompass实战:从零部署大模型评测平台,量化模型能力选型

在大模型技术选型与评估中,客观、可量化的评测体系是工程实践的关键。其核心原理在于通过标准化的数据集、统一的评测方法与自动化流程,将主观的模型体验转化为可比较的指标数据。这种评测框架的技术价值在于解决了模型能力评估的模糊性问题,为开发者提供了模型选型、效果对比与迭代优化的科学依据。典型的应用场景包括对比不同开源模型在代码生成、逻辑推理等特定任务上的性能,或是评估微调后模型在业务数据集上的提升效果。OpenCompass作为开源的大模型全能力评测平台,正是这一理念的工程化实现。它通过模块化的四层流水线架构和配置

weixin_28725037的博客 626

[POJ3255] Roadblocks(次短路)

传送门:Roadblocks 次短路算法模板题。 所谓次短路,同样可以利用 dijkstra 最短路算法求解。假设 dis[] 记录点的最短路,subdis[] 记录点的次短路,对于到达点 v 的某条路径长度 d,有几种可能的情况:①d < subdis[i] && d > dis[i],d 此时为次短路,更新 subdis[i] = d;② d > sub...

坤斤拷的博客 260

.NET MAUI跨平台串口通讯方案

MAUI跨平台串口通信架构设计采用分层模式,核心是共享业务逻辑层与平台特定实现。通过定义统一的ISerialPortService接口,实现了Windows、Android、iOS和macOS四大平台的串口通信功能。Windows平台使用System.IO.Ports类库,Android通过USB Host模式实现,iOS基于ExternalAccessory框架,macOS则采用IOKit。该设计支持串口连接管理、数据收发等核心功能,并通过事件机制实现异步通信。架构采用条件编译区分各平台实现,确保代码复用

冰茶的博客 1663

MediaCodec视频解码流程详解及参考demo

本文主要讲解mediacodec的视频解码流程,及demo参考例子。

分享音视频技术 7872

「次短路」学习笔记

不是最短的,那就是第二短的,也就是除最短路外最短的路径我们尝试用最短路来求次短路,可以想到我们可以得到一些最短路与次短路之间的一些关系根据这两点我们就可以求次短路了,以下面这题为例[USACO06NOV] Roadblocks G 此外还可以写一下 AcWing 观光这题就是在最短路和算次短路的基础上,计算路径数量最短路计数:次短路计数:分为两种情况:

小跳蛙的大本营 371

LangChain入门(二)-通过 Google 搜索并返回答案

并复制他给我们生成 api key。(博主使用了GitHub账号登录)-邮箱验证-手机号验证-订阅-api-key。Serpapi 提供了 google 搜索的 api 接口。首先需要我们到 Serpapi 官网上注册一个用户,

Good Luck 1万+

HDU6181-求解次短路-A*或者dijkstra

(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 题意:传送门  原题目描述在最下面。  次短路裸题。 思路:  在dijstra的过程过维护两个数组变量:\(dis1[],dis2[]\)。分别表示到达\(i\)节点的最短距离和次短距离。  如果当前距离大于次短距离,则更新次短距离。如果更新后次短距离小于最短距离,就交换二者的值。到最后两个数组值就更新就完成了。 ...

ako2654的博客 158

人工智能面试总结-Python

B站:啥都会一点的研究生 公众号试读:啥都会一点的研究生 目录说说Python程序运行过程?说说Python的作用域?说说Python的数据结构?说说Python中可变与不可变类型?说说进程与线程?说说Python中的多线程?说说Python中的多进程?说说Python互斥锁与死锁?说说Lambda?说说Python的深拷贝与浅拷贝?说说Python多线程是否能用多个CPU,为什么?说说Python垃圾回收机制?说说Python里的生成器?说说迭代器与生成器的区别?说说Python 列表的 del,rem.

啥都生的博客 1万+

24、虚拟地理信息系统:技术与应用的全面解析

本文全面解析了虚拟地理信息系统(虚拟GIS)的技术架构与应用前景。文章从地理空间数据的增长出发,探讨了虚拟GIS在地形、建筑、天气等多维度数据的交互式可视化技术,重点介绍了全球层次结构、多分辨率模型、缓存分页机制及交互导航方法。系统已应用于天气分析、城市规划、应急响应等领域,并展望了未来在数据处理、模拟操作、移动可视化及智能城市、文化遗产保护等方向的发展路径与技术挑战。

v4w5x6的博客 88

2017多校第10场 HDU 6181 Two Paths 次短路

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6181 题意:给一个图,求出次短路。 解法:我之前的模板不能解决这种图,就是最短路和次短路相等的情况,证明这题数据还是水了。下来我修改了一下次短路的,就可以避免这种情况了。提供一个sample 4 4 (1,2,1)( 1, 3,1) (2 4,1) (3 ,4,1)。这组的正确答案是2...

aishangg437965的博客 147

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

poj 3255 Roadblocks Dijkstra求次短路

Roadblocks Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7067   Accepted: 2626 Description Bessie has moved to a small farm and sometimes enjoys returning

渭城朝雨浥轻尘 909

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Dijkstra次短路

Dijkstra次短路 其实就是带入两个变量进行增广,一个表示最短,一个表示次短。 接下来讲一下如何用堆维护,每当更新到了最短或次短,就将这个答案put进堆里就可以了。堆的大小不是很清楚,建议用调优先队列。 例题 传送门 代码如下 #include<cstdio> #include<cctype> #include&...

aiweiluan5095的博客 154

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

严格次短路问题(洛谷P2865题解,Dijkstra算法应用)

次短路问题

水,全都是水 1152

(最短路深入)POJ 3463 - Sightseeing

题意: 给一个有向图,计算最短路和比最短路少1的路的条数的和。 分析: 这题真的写死我了。 因为之前很少接触最短路问题,所谓偶尔遇到一次也是套的模板,根本没有细细思考过dijsktra算法。所以栽在了这题上。 这题就是求最短路和次短路。 核心思想在于修改最短路松弛的条件,并且每个节点同时维护最短路和次短路。 很多博主写的很详细,我也不多说了,只是写个博文记录一下自...

dijieluan7764的博客 128

poj 3463 Sightseeing(最短路+次短路)

http://poj.org/problem?id=3463 大致题意:给出一个有向图,从起点到终点求出最短路和次短路的条数之和。 解法: 用到的数组:dis[i][0]:i到起点的最短路,dis[i][1]:i到起点的严格次短路 vis[i][0],vis[i][1]:同一维的vis数组,标记距离是否已确定 sum[i][0]:i到起点的最短路条数,sum[i][1]:

1398

<<算法竞赛进阶指南>>: 观光(单源最短路和单源次短路计数问题)

对于单源最短路计数问题,我们已经不陌生,但是对于单源次短路计数问题可能比较陌生,那么我们接下来看一道题, “您的个人假期”旅行社组织了一次比荷卢经济联盟的巴士之旅。 比荷卢经济联盟有很多公交线路。 每天公共汽车都会从一座城市开往另一座城市。 沿途汽车可能会在一些城市(零或更多)停靠。 旅行社计划旅途从 SSS 城市出发,到 FFF 城市结束。 由于不同旅客的景点偏好不同,所以为了迎合更多旅客,旅行社将为客户提供多种不同线路。 游客可以选择的行进路线有所限制,要么满足所选路线总路程为 SSS 到 FF

CPP2021的博客 405

poj3463 最短路和比最短路长1的路径数

这题需要很好的理解Dij。 在Dij的基础上,每个点多一个次短路的长度和数量进行控制。 那么在队列中,最短路控制时出现n次,次短路控制出现n次。注意松弛条件中val值和最短路、次短路的关系。 这题需要了解的是,对vis[i][0]控制确定每个点的最短路长度,对vis[i][1]控制确定每个点的次短路长度。 代码: #include #include #include #includ

amourjun的专栏 786

K短路

次短路 目前知道的方法有:1.跑一遍最短路,一次枚举删边 2.在跑最短路时同时记录最短路与次短路 3.起点和终点分别跑一次最短路,枚举边来替换最短路上的边 例题P1491 集合位置 #include<cstdio> #include<cmath> #include<queue> #include<cstring> using namespace std; typedef pair<double, int> PDI; const int INF =

A2484337545的博客 338

算法笔记--次小生成树 && 次短路 && k 短路

1.次小生成树 非严格次小生成树:边权和小于等于最小生成树的边权和 严格次小生成树: 边权和小于最小生成树的边权和 算法:先建好最小生成树,然后对于每条不在最小生成树上的边(u,v,w)如果我们把它放到最小生成树中,会形成一个环,那么再从这个环上删除一个除加进去的边外且小于(或等于)当前w的最大权值边,可以用倍增(或树剖)维护链上的最大值来实现非严格的,对于严格的来说,最大值可能等于w...

weixin_34278190的博客 133
上一篇: 递推、递归:将大目标分解为小目标的处理方法
下一篇: 初等数论基础知识详细解析(1)
Aobing_peterJr
博客等级 码龄2年 128粉丝 18原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值