最短路问题——K短路问题 / 次短路问题

最短路问题


        最短路问题中的非常著名的Dijkstra算法、Floyd-Warshall算法以及经典的练习题,大家可以去下面的链接看哈。
Dijkstra算法

Floyd-Warshall算法

一、K 短路问题

A*算法

        给定一个图,定义起点 𝑠 和终点 𝑡,以及数字 𝑘;求 𝑠 到 𝑡 的第 𝑘 短的路。允许环路。相同长度的不同路径,也被认为是完全不同的。

思路:

        用A*算法求解。把从 𝑠 到 𝑡 的路径分为两部分:从 𝑠 到中间某个 𝑖 的路径、从 𝑖 到 𝑡 的路径。估价函数 f(i) = g(i) + h(i),𝑔(𝑖) 是从 𝑠 到 𝑖 的路径长度,ℎ(𝑖)是从 𝑖 到 𝑡 的路径长度。𝑔(𝑖) 用 BFS 搜索;ℎ(𝑖) 是从 𝑖 到 𝑡 的最短路长度,用 dijkstra 计算得到。

代码:

  1. 用邻接表存图;
  2. dijkstra() 函数是标准的模板;
  3. astar() 函数实际上就是一个简单的“BFS+优先队列”,当终点 𝑡 第 𝑘 次从优先队列中弹出时,就是从 𝑠 到 𝑡 的第 𝑘 短路。

当 𝑘=1 时,第 1 短路就是最短路。

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;const int INF = 0x3f3f3f3f;
const int maxn = 1005, maxm = 100005;/// 记录边
struct edge {          int to, w;// vector edge[i]:起点是i; 它有很多边,其中一个边的to是边的终点,w是边长edge(int a, int b) { to = a, w = b; } //赋值
};/// G:原图  G2:反图
vector <edge>G[maxm], G2[maxm];  /// 用于dijkstra。记录点,以及点到起点的路径
struct node {      int id, dis;   //id:点;dis:点id到起点的路径长度node(int a, int b) { id = a, dis = b; } //赋值bool operator < (const node& u) const { return dis > u.dis; }
};int  dist[maxn];   //dist[i]: 从s到点i的最短路长度
bool done[maxn];   //done[i]=ture: 表示到i的最短路已经找到
/// 标准的dijkstra: 求s到其他所有点的最短路
void dijkstra(int s) {    for (int i = 0;i < maxn;i++) { dist[i] = INF; done[i] = false; }  //初始化dist[s] = 0;					//起点s到自己的距离是0priority_queue<node> q;q.push(node(s, dist[s]));		//从起点开始处理队列while (!q.empty()) {node u = q.top();			//pop出距起点s最近的点uq.pop();if (done[u.id])  continue;	//丢弃已经找到最短路的点            done[u.id] = true;			//标记:点u到s的最短路已经找到for (int i = 0; i < G2[u.id].size(); i++) {		//检查点u的所有邻居edge y = G2[u.id][i];if (done[y.to])   continue;					//丢弃已经找到最短路的邻居                if (dist[y.to] > u.dis + y.w) {dist[y.to] = u.dis + y.w;q.push(node(y.to, dist[y.to]));			//扩展新的邻居,放进优先队列}}}
}/// 用于 astar
struct point {      int v, g, h;    //评估函数 f = g + h, g是从s到i的长度,h是从i到t的长度point(int a, int b, int c) { v = a, g = b, h = c; }bool operator < (const point& b) const { return g + h > b.g + b.h; }
};int times[maxn];	//times[i]: 点i被访问的次数
int astar(int s, int t, int k) {memset(times, 0, sizeof(times));priority_queue<point> q;q.push(point(s, 0, 0));while (!q.empty()) {point p = q.top();					//从优先队列中弹出f = g + h最小的q.pop();times[p.v]++;if (times[p.v] == k && p.v == t)	//从队列中第k次弹出t,就是答案return p.g + p.h;for (int i = 0; i < G[p.v].size(); i++) {edge y = G[p.v][i];q.push(point(y.to, p.g + y.w, dist[y.to]));}}return -1;
}int main() {int n, m;scanf("%d%d", &n, &m);while (m--) {int a, b, w;					//读边:起点、终点、边长scanf("%d%d%d", &a, &b, &w);	//本题是有向图G[a].push_back(edge(b, w));		//原图G2[b].push_back(edge(a, w));	//反图}int s, t, k;scanf("%d%d%d", &s, &t, &k);if (s == t)  k++;					//一个小陷阱dijkstra(t);						//在反图G2上,求终点t到其他点的最短路printf("%d\n", astar(s, t, k));		//在原图G上,求第k短路return 0;
}

二、次短路问题

        给出一个图,包括 𝑛 个点,1≤𝑛≤5000,𝑚 条边,1≤𝑚≤100000。问从起点 11 到终点 𝑛 的第二短路的长度。

        第二短的路径中,可以包含任何一条在最短路中出现的道路,并且,一条路可以重复走多次。当然,第二短路的长度必须严格大于最短路(可能有多条)的长度,但它的长度必须不大于所有除最短路外的路径的长度。

思路:

        次短路问题即当 𝑘=2 时的第 𝑘 短路问题,用前面求第 𝑘 短路的 A* 算法就能处理了。

        只要把前面的代码简单修改三处:

  1. 修改第 7 行的 maxn 和 maxm 为本题的规模
  2. 第 81∼82 行,按双向边读图
  3. 第 88 行,改为 astar(1, n, 2)

        当然这个问题还个有更简单的解法:从起点 𝑠 到图上某个点 𝑣 的最短路长度 𝑃𝑣​ 容易计算,而 𝑠−𝑣 的次短路,肯定是从 𝑣 的某个邻居 𝑢 过来的,它是两种情况之一:

  1. 𝑠−𝑢 的最短路加上边 𝑢−𝑣,总长度为 𝑃1​
  2. 𝑠−𝑢 的次短路加上边 𝑢−𝑣,总长度为 𝑃2​

        比最短路 𝑃𝑣 大一点的 𝑃1 或 𝑃2​ 就是 𝑠−𝑣 的次短路长度,做一次 Dijkstra 计算每个点的最短路和次短路即可,复杂度和只求最短路一样也是 𝑂(𝑚𝑙𝑜𝑔𝑛) 的,比前面用A*算法求次短路稍好一点。

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

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

相关文章

跟我学C++中级篇——内联

一、内联函数 内联函数的定义有各种形式&#xff0c;这里只提一种百度百科上的定义&#xff1a;“在计算机科学中&#xff0c;内联函数&#xff08;有时称作在线函数或编译时期展开函数&#xff09;是一种编程语言结构&#xff0c;用来建议编译器对一些特殊函数进行内联扩展&a…

有趣的大模型之我见 | Claude AI

最近我的朋友圈被 Claude 3 严重刷屏。因为它在 Performance Benchmark 和 Vision Capabilities 中的表现荣登第一。 对 Claude AI 的喜欢是从它第二个版本出来。仅从我个人的简单应用场景的体验是&#xff0c;Claude 对于 prompt 的理解度&#xff0c;尤其是对中文的理解度高…

PHP源码_在线艺术字体在线生成转换设计网站源码

最全的字体转换器在线转换、艺术字体在线生成器和字体下载&#xff0c;包括书法字体在线转换、毛笔字在线生成器&#xff0c;更有草书字体、篆体字、连笔字、POP字体转换器等中文和英文字体。 支持自己添加字体&#xff0c;在线艺术字体转换器&#xff0c;织梦内核艺术字体在线…

Java 高级面试问题及答案(二)

Java 高级面试问题及答案 问题1: 什么是Java内存模型(JMM)&#xff0c;它在多线程编程中扮演什么角色&#xff1f; 答案&#xff1a; Java内存模型(JMM)定义了Java程序中各种变量的访问规则&#xff0c;尤其是多线程环境下的可见性、原子性和有序性。JMM确保了在多线程环境下…

.NET操作 Access (MSAccess)

注意&#xff1a;新项目推荐 Sqlite &#xff0c;Access需要注意的东西太多了&#xff0c;比如OFFICE版本&#xff0c;是X86还是X64 连接字符串 ProviderMicrosoft.ACE.OleDB.15.0;Data Source"GetCurrentProjectPath"\\test.accdb//不同的office版本 连接字符串有…

MySQL Workbench 数据库常用操作

大家好哦&#xff0c;我是程序员徐师兄&#xff0c;今天为大家打来的是MySQL Workbench 数据库常用操作。 文章目录 一、连接数据库二、进入数据库三、创建数据库四、设置默认数据库五、创建数据表六、查看表数据七、查看数据表 一、连接数据库 二、进入数据库 三、创建数据库 …

Shopee怎么选品成功率高达80%?请学

电商圈内流传着一句话&#xff1a;三分靠运营&#xff0c;七分靠选品。 选品在电商项目中至关重要&#xff0c;也是一个非常考验技巧和经验的环节。选品选择得好&#xff0c;后续的每一步都会变得相对轻松。 那么要怎么在众多商品中脱颖而出&#xff0c;提高在Shopee平台上选…

Llama images - 记录我看到的那些羊驼

来自 &#xff1a; DREAM: Distributed RAG Experimentation Framework

Git中标签(Tag)的使用

在Git中&#xff0c;标签是一种轻量级的指针&#xff0c;它指向某个特定的提交。与分支不同的是&#xff0c;标签通常用于标记重要的提交&#xff0c;如发布版本。标签是静态的&#xff0c;一旦指向某个提交&#xff0c;通常不会再改变。在本文中&#xff0c;我们将介绍Git中标…

如何用智能获客开启新商机?揭秘赢销侠软件的奇效

在当今数字化竞争日益激烈的商业环境中&#xff0c;企业为了生存和发展&#xff0c;必须寻找新的途径以获取潜在客户。智能获客作为一种新型的营销方式&#xff0c;正以其高效、精准的特点改变着传统的市场开拓模式。而在这个过程中&#xff0c;自动获客软件的作用愈发凸显&…

Adobe推出AI视频超分辨率工具VideoGigaGAN

&#x1f989; AI新闻 &#x1f680; Adobe推出AI视频超分辨率工具VideoGigaGAN 摘要&#xff1a;Adobe公司最新推出的AI工具VideoGigaGAN&#xff0c;利用上采样技术将视频分辨率从128128提升至10241024。这一工具基于GigaGAN模型开发&#xff0c;专注于生成视频超分辨率&am…

《深入解析windows操作系统》第1章读书笔记

1、服务&#xff1a;指操作系统中可以被调用的例程&#xff08;即函数&#xff0c;等价于系统调用&#xff1f;&#xff09;、设备驱动程序或者服务器进程。一些特定术语如下&#xff1a; 1&#xff09;Windows API函数&#xff1a;指Windows API中已经被文档化、可被调用的子例…

Java Spring 支持哪些类型的事务传播行为?

Spring框架支持的事务传播行为&#xff08;Propagation Behavior&#xff09;是Spring事务管理的一个重要概念。事务传播行为定义了当一个事务方法被另一个事务方法调用时&#xff0c;应该如何处理这两个事务之间的关系。Spring定义了七种不同的事务传播行为&#xff0c;每种行…

TCP重传,滑动窗口,流量控制,拥塞控制

TCP重传&#xff0c;滑动窗口&#xff0c;流量控制&#xff0c;拥塞控制 TCP重传机制&#xff1a; 超时重传快速重传SACKD-SACK 通过序列号与确认应答判断是否要重传 超时重传&#xff1a; 超过指定时间没有收到确认应答报文&#xff0c;就会重发该数据 触发超时重传的情况…

SpirngBoot整合快递100

目录 一、注册快递100 二、技术文档地址 三、需要认证的key和comcumer 四、spring boot 整合快递 100使用 4.1 引入快递100和hutool的依赖 4.2 将key和comcumer写入application.properties文件中 4.3 新建一个modle,用于将查出来的json数据转成对象 4.4 新建一个controll…

MySql-日期分组

一、分别统计各时间各类型数据条数 数据库的 request_time字段 数据类型&#xff1a;timestamp 默认值&#xff1a;CURRENT_TIMESTAMP 例子&#xff1a; 2024-01-26 08:25:48 原数据&#xff1a; 1、将数据按照日期&#xff08;年月日&#xff09;形式输出 按照request_…

5A手控问道手游戏抢装备说明手册

5A手控-问道抢装备方法 下载软件地址&#xff1a;www.aishouk.com 支持win10 和win 11 系统 下载&#xff0c;安装完成后&#xff0c;打开软件。 下载最好选择 CSDN 或者 百度网盘下载 &#xff0c;官网下载速度很慢。这点大家 需要注意。 注册/登录 打开软件&#xff0c;点…

Mellanox网卡打流命令ib_write_bw执行遇到Couldn‘t listen to port 18515原因与解决办法?

要点 要点&#xff1a; ib默认使用18515命令 相关命令&#xff1a; netstat -tuln | grep 18515 ib_write_bw --help |grep port# server ib_write_bw --ib-devmlx5_1 --port 88990 # client ib_write_bw --ib-devmlx5_0 1.1.1.1 --port88990现象&#xff1a; 根因&#xf…

首页最新 多IP浏览器防关联:如何配置多个独立且稳定的IP地址?

在互联网时代&#xff0c;IP地址的重要性不言而喻。然而&#xff0c;IP关联问题却成为一项令人担忧的隐私和安全挑战。针对这个问题&#xff0c;多IP浏览器是一种解决方案&#xff0c;可以帮助用户单独配置多个独立且稳定的IP地址&#xff0c;有效地防止IP关联。 一、IP关联是…

ipad的文件如何传到手机里 iPad较大文件怎么发送出去 iMazing下载教程

在现代生活中&#xff0c;随着移动设备的普及和多样化&#xff0c;我们经常需要在不同设备之间传输文件&#xff0c;以便在工作、学习或娱乐中更加便捷地使用这些文件。iPad和iPhone是用户广泛使用的设备&#xff0c;我们时常使用它们来存储和访问大量的个人数据。但有时&#…