图论(五)-最短路

一、Bellman-Ford算法 

        算法思想:通过 n 次循环,每次循环都遍历每条边(共 m 条边),进而更新节点的距离,每次循环至少可以确定一个点的最短路,循环 n 次,求出 n 个点的最短路

        时间复杂度 : O(mn)  (n为节点个数,m为边总数)

        与前面所述的dijkstra算法不同,Bellman-Ford 算法可以处理含负权边的单源最短路问题,同时可以判断是否存在负权回路。

        算法描述:

        ①初始化:将除起始点 s 以外的 dis 数组设置为 无穷大, dis[ s ] = 0

        ②迭代:遍历图中的每条边,对边的两个顶点分别进行松弛操作,一共遍历 n 次 m条边,直到没有节点能够松弛

        ③判断负环:Bellman-Ford算法迭代后,再迭代一次,若最短路距离发生改变,则存在负环。

        核心代码:

for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
    int u=edge[i].u;
    int v=edge[i].v;
    int w=edge[i].w;
  	 if(dist[u]+v<dist[v])
  	   dist[v]=dist[u]+w; //松弛
}

应用

        Bellman-Ford算法,第 i 次循环 m 条边时,可以确定走 i 条路到达的点的最短距离。 当图为一条直线时,需要 n-1 次循环即可确定最短路。

求有边数限制的最短路

        通过上述 Bellman-Ford算法思路,若求 k 条边数限制的最短路,仅需要循环 k 次 m条边,以下图举例说明。

        

    k = 1 时,通过上述代码,遍历一次即可算出 节点2 3 的最短路,但是这是错误的。当边的顺序为 (2,3,3)  (1,2,2) 时,遍历一次仅可以求出 节点2 的最短路,说明上述仅遍历一次得出的 节点3 不一定是最短路。

    考虑原问题,若需要求 k 条边限制的最短路

     通过第一种情况边的顺序可以得出 dis[ 3 ] 为 5 ,可是显然仅走1条边时到达不了节点3

     而通过第二种情况边的顺序又可以得出正确结果。但是当节点数明显增多时,边的顺序无法自行更改,应该如何处理?

        进行备份,保存其上一[2] 应为第0条边时的值(正无穷),同时将备份数组不断更新。层的状态,对该状态进行松弛操作(即当考虑第k条边时,对其考虑第 k-1 条边的状态进行松弛操作),在上述图例中,当对 节点3 进行松弛操作的 dis

        此外,当存在负权边时,仍然会更新,可是更新后的大小为 正无穷+负权值,在最后判断是否到达该节点时仅需判断 

if ( dist [n] > 0x3f3f3f3f/2 ) return -1;

核心代码:

memset(dis,0x3f,sizeof(dis));
dist[1]=0;
for(int i=1;i<=k;i++) 
{
    for(int j=1;j<=n;j++) bf[i]=dis[i];
	for(int j=1;j<=m;j++)   // 枚举所有边 
	{
		 int a=edge[j].a,b=edge[j].b,w=edge[j].w;	
		 dis[b]=min(dis[b],bf[a]+w); // 用备份更新 
	}
}
if(dist[n]>0x3f3f3f3f/2) return -1;
return dist[n];

二、SPFA算法

        SPFA算法是在上述 Bellman-Ford 基础上优化得来的,Bellman-Ford中,当某个点未被更新过,仍会用该点去更新其他节点,这是无意义的,使得效率降低,SPFA中将更新后的节点再去更新其他节点即可。

void spfa()
{// 将更新的节点加入队列中,队列中的元素即为已更新的节点
	memset(dis,0x3f,sizeof(dis));
	dist[1]=0;
	queue<int>q;
	q.push(1); //入队 
	st[1]=1; // 队列中含有该节点
	while(q.size()) // 队列不空
	{
	   int u=q.front(); 
	   q.pop();
	   st[u]=0; // 出队
	   for(int i=head[u];i!=-1;i=edge[i].next)
	   {
	   	 int v=edge[i].v;
	   	 int w=edge[i].w; 
         if(dis[v]>dis[u]+w)
	   	 {
	   	    dis[v]=dis[u]+w;
			if(!st[v])  //如果不在队列中,入队
			{
				q.push(v); 
				st[v]=1;		    } 	    	
		 }
	   }	
	} 
}

SPFA应用:判断负环

        负环:当图中存在一个环,使得绕环遍历一圈的结果为负数,这样绕该环一直遍历,最短距离不断减小,不存在最短路

SPFA判断负环:用一个 cnt [x] 数组存储 起点到 x 点的最短路径经过的边数,因为SPFA为最短路算法,经过的边数一定<n ,若 cnt 数组的某个值 >=n , 则说明存在负环。

        此外,通过链式前向星构建的图不一定是连通的,可能存在自环的情况(负自环),因此需要首先将所有节点入队。

bool spfa()
{// 将更新的节点加入队列中,队列中的元素即为已更新的节点
	memset(dis,0x3f,sizeof(dis));
	dist[1]=0;
	queue<int>q;
    for(int i=1;i<=n;i++)
    {
	    q.push(i); //入队 
	    st[i]=1; // 队列中含有该节点
	}
    while(q.size()) // 队列不空
	{
	   int u=q.front(); 
	   q.pop();
	   st[u]=0; // 出队
	   for(int i=head[u];i!=-1;i=edge[i].next)
	   {
	   	 int v=edge[i].v;
	   	 int w=edge[i].w; 
         cnt[v]=cnt[u]+1;
         if(cnt[v]>=n) return true; // 经过边数>=n,存在负环
         if(dis[v]>dis[u]+w)
	   	 {
	   	    dis[v]=dis[u]+w;
			if(!st[v])  //如果不在队列中,入队
			{
				q.push(v); 
				st[v]=1;
		    } 	    	
		 }
	   }	
	} 
}

三、Floyd 算法

        Floyd 算法可以实现多源最短路,思想基于动态规划,从 节点i 到 节点j 的路径有两种

        1.从 节点i 直接到 节点j  dis[i][j]=dis[i][j]

        2. 节点i 经过某些节点到达 节点k 再经过某些节点到达 节点j   dis[i][j]=dis[i][k]+dis[k][j] 

        通过上面两种方式进行更新

        时间复杂度为 O(n^{3} )

void floyd()
{
 for(int k=1;k<=n;k++)
   for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
      d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

opencascade V3d_RectangularGrid 源码学习

类V3d_RectangularGrid V3d_RectangularGrid() V3d_RectangularGrid::V3d_RectangularGrid(const V3d_ViewerPointer &aViewer, const Quantity_Color &aColor, const Quantity_Color &aTenthColor) // 构造函数 ◆ ~V3d_RectangularGrid() virtual V3d_Rectang…

YOLOv10最详细全面讲解1- 目标检测-准备自己的数据集(YOLOv5,YOLOv8均适用)

YOLOv10没想到出来的如此之快&#xff0c;作为一名YOLO的爱好者&#xff0c;以YOLOv5和YOLOv8的经验&#xff0c;打算出一套从数据集装备->环境配置->训练->验证->目标追踪全系列教程。请大家多多点赞和收藏&#xff01;&#xff01;&#xff01;YOLOv5和YOLOv8亲测…

Simulink从0搭建模型06-P7模型中结构体的使用

Simulink从0搭建模型06-P7模型中结构体的使用 本节课学习内容1. 结构体的创建 Bus Creator&#xff08;多输入单输出&#xff09;2. 结构体的引用 Bus Selector&#xff08;单输入多输出&#xff09;3. 结构体的赋值 Bus Assignment4. 结构体对象的创建 Bus object5. 结构体数组…

10分钟掌握FL Studio21中文版,音乐制作更高效!

FL Studio 21中文版是Image Line公司推出的一款深受欢迎的数字音频工作站软件&#xff0c;在音乐制作领域享有盛誉。这个版本特别针对中文用户进行了本地化处理&#xff0c;旨在提供更加便捷的用户体验和操作界面。本次评测将深入探讨FL Studio 21中文版的功能特点、使用体验及…

Java RMI

RMI - 安全篇 RMI分为三个主体部分&#xff1a; *Client-客户端*&#xff1a;客户端调用服务端的方法 *Server-服务端*&#xff1a;远程调用方法对象的提供者&#xff0c;也是代码真正执行的地方&#xff0c;执行结束会返回给客户端一个方法执行的结果。 *Registry-注册中心…

防火墙技术基础篇:配置主备备份的双机热备

防火墙技术基础篇&#xff1a;配置主备备份的双机热备 防火墙双机热备&#xff08;High Availability, HA&#xff09;技术是网络安全中的一个关键组成部分&#xff0c;通过它&#xff0c;我们可以确保网络环境的高可靠性和高可用性。下面我们一起来了解防火墙双机热备的基本原…

第二十三届中国科学家论坛盛大开幕,星医联董事长杨星荣获“十四五”科技创新先锋人物

2024年5月25-26日&#xff0c;第二十三届中国科学家论坛在北京召开&#xff0c;北京星医联科技有限公司&#xff08;以下简称“星医联”&#xff09;董事长杨星女士受邀出席并荣获“十四五科技创新先锋人物”称号。同时星医联专利“一种靶向协同降脂的纳米双药制备及应用”荣获…

[CVPR-24] HUGS: Human Gaussian Splats

本文提出一种新的数字人表征Human Gaussian Splats (HUGS)&#xff0c;可以实现新姿态和新视角生成&#xff1b;本文提出一种新的前向形变模块&#xff08;forward deformation module&#xff09;&#xff0c;在标定空间基于Gaussians表征数字人&#xff0c;并基于LBS学习如何…

从 ASCII 到 UTF-8 - Unicode 码的诞生与实现

前言&#xff1a;最近我在整理过往笔记时&#xff0c;发现涉及到了 UTF-8、Unicode 的相关内容&#xff0c;相信大家中的很多人和之前的我一样&#xff0c;在过去的很长一段时间里&#xff0c;并没有搞清楚什么是 Unicode、什么是 UTF-8&#xff0c;于是就有了这篇文章&#xf…

SSL证书:守护个人信息安全的坚固盾牌

在数字化浪潮汹涌的今天&#xff0c;我们的个人信息如同一座座宝藏&#xff0c;吸引着不法分子的贪婪目光。数据泄露事件频发&#xff0c;让信息安全问题日益凸显。而在这个信息爆炸的时代&#xff0c;如何保护我们的个人信息安全&#xff0c;成为了一个亟待解决的问题。幸运的…

【第三节】类的构造和析构函数

目录 一、数据成员的初始化 二、构造函数 2.1 什么是构造函数 2.2 构造函数的注意事项 三、析构函数 四、带参数的构造函数 五、缺省构造函数 六、构造函数初始化列表 七、拷贝构造函数和调用规则 八、深拷贝和浅拷贝 九、总结 一、数据成员的初始化 定义普通变量&am…

java智慧工厂制造生产管理MES系统saas模式Java+ idea+ uniapp全套MES系统源码,多端展示

java智慧工厂制造生产管理MES系统saas模式Java idea uniapp全套MES系统源码&#xff0c;多端展示 MES 系统源码&#xff08;生产制造执行系统&#xff09;能够帮助企业实现全生产过程的可视化&#xff0c;数据分析智能化、构建高效智能工厂&#xff0c;MES系统通过控制指令、人…

大气污染溯源算法及其技术实现

污染溯源基础概念知识 大气污染溯源是指识别并追踪污染物的来源及其传输过程&#xff0c;以确定造成大气污染的根本原因和污染物传播路径的技术和方法。这对于制定有效的控制和减轻污染策略至关重要。大气污染的溯源主要涉及以下几个方面&#xff1a; 污染源识别&#xff1a;…

Facebook开户 | 如何检查公共主页的状态

想要了解你的Facebook公共主页的状态吗&#xff1f; Facebook公共主页是让广告主与粉丝互动、传播信息的绝佳平台&#xff0c;但是大家知道如何检查并维护自己的主页状态吗&#xff1f;别担心&#xff0c;Facebook提供了一系列简单易用的工具来帮助大家实现这一目标。 *Page Q…

RedHat9网络配置设计

目录 一、实验目的 二、实验过程 1、配置新网络接口 2、多网卡配置网络 3、网络接口的绑定&#xff0c;进行远程访问 4、配置网络接口的组合 一、实验目的 本次实验的目的是使用nmcli命令工具配置网络&#xff0c;ens160配置多个网卡&#xff0c;进行网络接口的绑定与组合…

一文搞懂Java8 Lambda表达式、方法引用

Lambda表达式介绍 Java 8的一个大亮点是引入Lambda表达式&#xff0c;使用它设计的代码会更加简洁。通过Lambda表达式&#xff0c;可以替代我们以前经常写的匿名内部类来实现接口。Lambda表达式本质是一个匿名函数&#xff1b; 体验Lambda表达式 我们通过一个小例子来体验下L…

单元测试框架Pytest的基本操作

Pytest基本操作 1. 详解1.1 命名规则:1.2 自定义查找规则:1.3 3种运行方式1.4 执行顺序2. 断言2.1 定义2.2 断言的规则3. mark3.1 mark的作用3.2 mark的标记方式3.3 注册标签名3.4 skip跳过标记4. pytest的参数化5. pytest的夹具(fixture测试夹具)5.1. 作用5.2. 夹具应用场…

Java网络编程:UDP通信篇

目录 UDP协议 Java中的UDP通信 DatagramSocket DatagramPacket UDP客户端-服务端代码实现 UDP协议 对于UDP协议&#xff0c;这里简单做一下介绍&#xff1a; 在TCP/IP协议簇中&#xff0c;用户数据报协议&#xff08;UDP&#xff09;是传输层的一个主要协议之一&#xf…

LeetCode hot100-57-G

17. 电话号码的字母组合 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。不会&#xff0c;放IDEA里执行了一下大概理解了流程 …

《Ai企业知识库》-rasa-初步使用

根据上面的环境准备之后&#xff1a; 《Ai企业知识库》-模型实践-rasa开源学习框架-搭建简易机器人-环境准备(针对windows)-02-CSDN博客 基础的使用&#xff1a; rasa项目初始化&#xff1a; rasa init 首先进入目标文件夹 在dos窗口&#xff08;目标文件夹下&#xff09…