Bellman-Ford 与 SPFA 算法笔记_weixin_34080903的博客-程序员资料

个人笔记,仅供复习

1.Bellman-Ford算法

1.1 适用范围:含负权边的带权有向图的单源最短路问题。不能处理带负权边的无向图

1.2 限制条件:要求图中不能包含权值总和为负值回路(负权值回路),如下图所示:


1.3 算法思想:

1.3.1 构造dist[k][u]:算法构造了一个最短路径长度序列dist[k][u]。其中:

  • dist[1][u]是从源点v到终点u的只经过一条边的最短路径长度,并有dist[1][u] = Edge[v][u]
  • dist[2][u]为从源点v最多经过两条边到达终点u的最短路径长度
  • dist[3][u]为从源点v出发最多经过不构成负权值回路的三条边到达终点u的最短路径长度
  • dist[n-1][u]为从源点v出发最多经过不构成负权值回路的n-1条边到达终点u的最短路径的长度

算法的最终目的是计算出dist[n-1][u],为源点v到顶点u最短路径长度。

1.3.2 计算dist[k][u]:采用递推的方式计算dist[k][u]

  • 设已经求出dist[k-1][u],u = 0,1,2...,n-1;此即从源点v最多经过不构成负权值回路的k-1条边到达终点的最短路径长度
  • 从图的邻接矩阵可以找到各个顶点j到达顶点u的距离Edge[j][u],计算min{dist[k][j]+Edge[j][u]},可得从源点v绕过各顶点,最多经过不构成负权值回路的k条边到达终点u的最短路径长度
  • 比较dist[k-1][u]和min{dist[k][j]+Edge[j][u]},取较小者作为dist[k][u]的值

1.3.3 递推公式:dist[1][u] = Edge[v][u]

                         dist[k][u] = min{ dist[k-1][u] ,min{dist[k][j]+Edge[j][u]} },j = 0,1,...,n-1;j!=u

1.3.4 空间优化:由于计算出来dist[k][u]之后,dist[k-1][u]就没用了,所以我们可以只开一个一维数组dist[u]来不断更新它的值,算法结束时dist[u]中存放的就是dist[n-1][u]。


1.4 代码实例:

#define MAX_VER_NUM 10	//顶点个数最大值
#define MAX 1000000
int Edge[MAX_VER_NUM][MAX_VER_NUM];	//图的邻接矩阵
int vexnum;	//顶点个数
int path[MAX_VER_NUM]; //path[i]是i在最短路径中的上一个节点
void BellmanFord(int v) //假定图的邻接矩阵和顶点个数已经读进来了
{
	int i, k, u;
	for(i=0; i<vexnum; i++)
	{
		dist[i]=Edge[v][i];	//对dist[ ]初始化
		if( i!=v && dist[i]<MAX ) path[i] = v;	//对path[ ]初始化
		else path[i] = -1;
	}
for(k=2; k<vexnum; k++) //从dist1[u]递推出dist2[u], …,distn-1[u]
	{
		for(u=0; u< vexnum; u++)//修改每个顶点的dist[u]和path[u]
		{
			if( u != v )
			{
				for(i=0; i<vexnum; i++)//考虑其他每个顶点
				{
					if( Edge[i][u]<MAX &&
					    dist[u]>dist[i]+Edge[i][u] )
					{
						dist[u]=dist[i]+Edge[i][u];
						path[u]=i;
					}
				}
			}
		}
	}
}

1.5 Bellman算法与Dijkstra算法区别:

  • Dijkstra算法在求解过程中,源点到集合S内各顶点的最短路径一旦求出,则之后不变了,修改的仅仅是源点到T集合中各顶点的最短路径长度。
  • Bellman算法在求解过程中,每次循环都要修改所有顶点的dist[ ],也就是说源点到各顶点最短路径长度一直要到Bellman算法结束才确定下来。

2.SPFA算法

2.1 适用范围:SPFA算法是Bellman算法的改进版,它们是适用范围是相同的

2.2 算法思想:利用队列动态更新最小值

  • 设dist[i]代表s到i点的当前最短距离,fa代表s到i的当前最短路径的前一个点的编号。开始时dist初始值无穷大,只有dist[s] = 0,fa全为0。
  • 维护一个队列,里面存放所有需要进行迭代的点。初始时队列中只有一个点s,用一个布尔数组记录每个点是否在队列中。
  • 每次迭代,取出头节点v,依次枚举从v出发的边v->u,设边长度为len,如果dist[u] > dist[v]+len,则改进dist[u],将fa[u]记为v,并且由于s到u的最短距离变小了,有可能u可以改进其他的点,所以如果u不在队列里,就把它放进队尾。
  • 若一个点的最短路径被改进的次数达到n,则有负权环。可以通过SPFA算法判断图有无负权环。
2.3 代码实例:(邻接矩阵存图)
void spfa(int s){
	//dist[n]初始值无穷大
	dist[s] = 0;
	queue<int> q;
	q.push(s);
	vis[s] = true;//v在队列里
	while(q.empty()){//队列不为空 
		int v = q.front();
		q.pop();
		vis[v] = 0;//v已经不在队列中 
		for(int u = 0;u < n;u++){
			if(dist[u] > dist[v]+cost[v][u]){
				dist[u] = dist[v] + cost[v][u];
				fa[u] = v;
				updataTimes[u]++; //更新了多少次 
				if(vis[u] == 0)	q.push(u);
			}
		}
	} 
}

转载于:https://www.cnblogs.com/long98/p/10352229.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_34080903/article/details/93388826

智能推荐

mysql线程中断_#Thread线程:中断异常InterruptedException(*)_weixin_39580041的博客-程序员资料

在JDK1.0中,可以用stop方法来终止,但是现在这种方法已经被禁用了,改用interrupt方法。Thread.interrupt()方法不会中断一个正在运行的线程。它的作用是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(Inter...

面试题55 - I. 二叉树的深度 dps法与层次遍历法_achong_2050的博客-程序员资料

二叉树的深度 题目描述输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。例如:给定二叉树 [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7返回它的最大深度 3 。提示:节点总数 &lt;= 10000来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/er-cha-shu-de-

【线性代数公开课MIT Linear Algebra】 第二十四课 特征值与特征向量的应用——马尔科夫矩阵、傅里叶级数_马尔科夫矩阵 特征值_a352611的博客-程序员资料

本系列笔记为方便日后自己查阅而写,更多的是个人见解,也算一种学习的复习与总结,望善始善终吧~马尔科夫矩阵Markov Matrix 马尔科夫矩阵Markov Matrix有两个性质:所有元素大于等于0,所有矩阵的列相加等于1。这里性质导致一些有趣的特性:马尔科夫矩阵Markov Matrix 的幂依然是马尔科夫矩阵Markov Matrix马尔科夫矩阵Markov Matrix的其中一个特

macOS如何像windows一样去编写类似bat一样的批处理文件_mac 类似bat_iostyle的博客-程序员资料

在新公司使用了近两个月的windows开发,那是真的难受~~下周准备带自己的笔记本去上班,闲话少叙日常开发过程中,经常会用到一些adb的指令 比如从手机存储中pull一个log文件到pc,虽然代码不多,但毕竟懒才是推动程序员进步的源泉,我将cmd指令 adb pull /sdcard/xx.log D:/Temp/ 写成批处理文件 @echo off    IF EXIST C:\Us

Kinect开发学习笔记之(一)Kinect介绍和应用_kinect 将虚拟火焰附加到模型_lien0906的博客-程序员资料

Kinect开发学习笔记之(一)Kinect介绍和应用[email protected]://blog.csdn.net/zouxy09 一、Kinect简介      Kinectfor Xbox 360,简称 Kinect,是由微软开发,应用于Xbox 360 主机的周边设备。它让玩家不需要手持或踩踏控制器,而是使用语音指令或手势来操作 Xbox360

linux环境下使用netstat命令查看网络信息_ddi-tcp-2_AlbertS的博客-程序员资料

`netstat` 这个命令一直以为是 net status 的缩写,今天一查发现并没有找到官方的这种说法,然后参考了 man 手册,发现这个词更像是 net statistics 的缩写,命令的作用是显示网络连接、路由表、接口连接、无效连接和多播成员关系的...

随便推点

MyEclipse服务器远程调试_马院长的博客-程序员资料

这是一个关于讨论配置和调试在应用程序服务器上运行而不使用MyEclipse服务器启动连接器的应用程序的高级教程,无论MyEclipse是在 同一台计算机上运行或是在不同的计算机上运行都可。对于一般易于配置和调试的应用程序,强烈建议MyEclipse服务连接器可用于应用服务器中的所有服 务器操作详细教程。在执行本教程之前,请仔细阅读它。

基于Qt的音乐播放器(三)通过酷狗音乐的api接口,返回json格式歌曲信息(播放地址,歌词,图片)_歌词api接口_花狗Fdog的博客-程序员资料

文章目录前言1.获取歌曲搜索列表api接口2.获取单个歌曲详细信息包括歌词3.总结前言首先说明,本教程仅供个人学习,研究使用,禁止用于任何的商业和非法用途。(手动狗头)之所以要研究这个,是因为我想让我的播放器连上网络,而如果自己用数据库保存歌曲的相关信息不太现实,于是想到使用市面上的音乐软件,看看能不能找到api接口。最后声明,仅供学习使用,切莫用于商业用途。1.获取歌曲搜索列表api接口打开酷狗官网,在搜索栏中输入凤凰传奇,并按F12进入开发者工具,并选择Network(Network会显..

淘宝API开发系列:item_search-按关键字搜索淘宝商品 API 返回值说明_API技术爱好者的博客-程序员资料

为了进行淘宝的API开发,首先我们需要做下面几件事情。1)开发者注册一个账号2)然后为每个淘宝应用注册一个应用程序键(App Key) 。3)下载淘宝API的SDK并掌握基本的API基础知识和调用4)利用SDK接口和对象,传入AppKey或者必要的时候获取并传入SessionKey来进行程序开发。5)利用淘宝平台的文档中心和API测试工具,对接口进行测试。从而了解返回信息,方便程序获取。...

微信支付统一下单接口报错:nested exception is java.lang.NoClassDefFoundError: cn/hutool/core/util/IdUtil_九级代码狗的博客-程序员资料

微信支付统一下单接口报错:nested exception is java.lang.NoClassDefFoundError: cn/hutool/core/util/IdUtil

如何判断iphone设备型号和ios系统版本号_BigSoldierWu的博客-程序员资料

判断IOS设备类型一般会使用//设备名称return [UIDevice currentDevice].name;//设备型号,只可得到是何设备,无法得到是第几代设备return [UIDevice currentDevice].model;//系统版本型号,如iPhone OS return [UIDevice currentDevice].systemVersion;

翻页小实例_SuperHong123的博客-程序员资料

导入之后直接访问[url]http://localhost:8080/PageTurning/userList.do[/url]即可