Bellman-Ford&&SPFA算法详解
Dijkstra在正权图上运行速度很快,但是它不能解决有负权的最短路,如下图:
Dijkstra运行的结果是(以1为原点):0 2 12 6 14;
但手算的结果,dist[4]的结果显然是5,为什么会出现这种情况呢?原因很显然,Dijkstra认为,从一个更长的边过来不会比一个更短的边过来更短(读起来很绕口,但请读者好好理解这句话!)但是由于出现了负权边,可以“救回来”,就像松弛2号节点一样。
Bellman_Ford:
知道了Dijkstra为什么不能做负权图之后,我们来看看Bellman-ford算法。它的基本思想是:图的最短路,既不会包含正环(可以不走),更不能有负环(否则一直走就可以无限小),因此最多经过n-1条边(每个节点都经过一次),bellman-ford实际上是枚举距离源点多少条边,尝试对每条边松弛的过程。请读者联系上图,自行推导一下Bellman_ford的运行过程
样例如下:
5 5
1 2 2
1 3 12
3 2 -13
2 4 4
3 5 2
朴素Bellman_Ford算法的时间复杂度是O(NM);程序如下:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
int n,m,s,dist[],v[],w[],u[],cnt,x,y,z;
void bellman_ford(int s)
{
memset(dist,,sizeof(dist));
dist[s]=;
for(int i=;i<=n-;i++)
{
for(int j=;j<=m;j++)
{
dist[v[j]]=min(dist[v[j]],dist[u[j]]+w[j]);
}
}
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=;i<=m;i++)
{
scanf("%d %d %d",&u[i],&v[i],&w[i]);
}
bellman_ford();
for(int i=;i<=n;i++)
{
cout<<dist[i]<<" ";
}
return ;
}
SPFA:
SPFA是对Bellman_Ford算法的优化,它采用队列保存即将松弛其他点的节点,每次选与队首相连的点进行松弛,可以使用链式前向星(邻接表)实现,避免了Bellman_Ford算法许多无效的松弛操作,平均复杂度O(KM),K为平均松弛次数,也有可能被网格图卡回O(NM),是不稳定的算法。程序如下:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
int n,m,s,dist[],v[],w[],nxt[],head[],cnt,x,y,z;
bool vis[];
void add(int a,int b,int c)
{
v[++cnt]=b;
w[cnt]=c;
nxt[cnt]=head[a];
head[a]=cnt;
}
void SPFA(int s)
{
memset(dist,,sizeof(dist));
queue<int>q;
dist[s]=;
vis[s]=;
q.push(s);
while(!q.empty())
{
int c=q.front();
q.pop();
vis[c]=;
for(int i=head[c];i;i=nxt[i])
{
int y=v[i];
if(dist[y]>=dist[c]+w[i])
{
dist[y]=dist[c]+w[i];
if(!vis[y])
{
q.push(y);
vis[y]=;
}
}
}
}
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
SPFA();
for(int i=;i<=n;i++)
{
cout<<dist[i]<<" ";
}
return ;
}
Bellman-Ford&&SPFA算法详解的更多相关文章
- 图的最短路径-----------SPFA算法详解(TjuOj2831_Wormholes)
这次整理了一下SPFA算法,首先相比Dijkstra算法,SPFA可以处理带有负权变的图.(个人认为原因是SPFA在进行松弛操作时可以对某一条边重复进行松弛,如果存在负权边,在多次松弛某边时可以更新该 ...
- SPFA 算法详解
适用范围:给定的图存在负权边,这时类似Dijkstra等算法便没有了用武之地,而Bellman-Ford算法的复杂度又过高,SPFA算法便 派上用场了. 我们约定有向加权图G不存在负权回路,即最短路径 ...
- SPFA 算法详解( 强大图解,不会都难!) (转)
适用范围:给定的图存在负权边,这时类似Dijkstra等算法便没有了用武之地,而Bellman-Ford算法的复杂度又过高,SPFA算法便 派上用场了. 我们约定有向加权图G不存在负权回路,即最短路径 ...
- SPFA算法详解
前置知识:Bellman-Ford算法 前排提示:SPFA算法非常容易被卡出翔.所以如果不是图中有负权边,尽量使用Dijkstra!(Dijkstra算法不能能处理负权边,但SPFA能) 前排提示*2 ...
- Bellman-Ford算法与SPFA算法详解
PS:如果您只需要Bellman-Ford/SPFA/判负环模板,请到相应的模板部分 上一篇中简单讲解了用于多源最短路的Floyd算法.本篇要介绍的则是用与单源最短路的Bellman-Ford算法和它 ...
- 【最短路径Floyd算法详解推导过程】看完这篇,你还能不懂Floyd算法?还不会?
简介 Floyd-Warshall算法(Floyd-Warshall algorithm),是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似.该算法名称以 ...
- BM算法 Boyer-Moore高质量实现代码详解与算法详解
Boyer-Moore高质量实现代码详解与算法详解 鉴于我见到对算法本身分析非常透彻的文章以及实现的非常精巧的文章,所以就转载了,本文的贡献在于将两者结合起来,方便大家了解代码实现! 算法详解转自:h ...
- kmp算法详解
转自:http://blog.csdn.net/ddupd/article/details/19899263 KMP算法详解 KMP算法简介: KMP算法是一种高效的字符串匹配算法,关于字符串匹配最简 ...
- 机器学习经典算法详解及Python实现--基于SMO的SVM分类器
原文:http://blog.csdn.net/suipingsp/article/details/41645779 支持向量机基本上是最好的有监督学习算法,因其英文名为support vector ...
随机推荐
- 完美的Linux之【navi】使用笔记
今天要说的是才上线才两天,就已经获得超过1000星.开发者是一位来自巴西的小哥Denis Isidoro. 开发的工具navi Linux用户的日常困惑 新命令 用完就忘 ? 一时想不起来命令的单词怎 ...
- c# 添加数据
/// <summary> /// 新增一条省份记录 /// </summary> /// <param name="model"></p ...
- windows使用ubuntu启动linux服务
有些服务只能在linux中策马奔腾,但是公司配置windows电脑,因此在windows中安装ubuntu服务,再在启动的ubuntu中启动linux服务 系统:win10(其他系统没试过) 安装步骤 ...
- Sass函数:数字函数-ceil()函数
ceil() 函数将一个数转换成最接近于自己的整数,会将一个大于自身的任何小数转换成大于本身 1 的整数.也就是只做入,不做舍的计算: >> ceil(2.0) 2 >> ce ...
- runltp出现问题 [
runltp 623行: if [ "$?" == "0" ]; then 对[解析出了问题. 我灵机一动,是不是sh的问题. which sh /bin/sh ...
- html5中play 方法和pause方法在video的应用
play();播放 pause();暂停 代码实例: <!DOCTYPE html> <html lang="en"> <head> <m ...
- 【串线篇】Mybatis缓存之二级缓存
1.应用 二级缓存:namespace级别的缓存:SqlSession关闭或者提交以后有效 一级缓存:SqlSession关闭或者提交以后,一级缓存的数据会放在二级缓存中: 二级缓存的使用:mybat ...
- JS基础入门篇(四十三)—ES6(二)
1.对象简洁表示法 原来写法 var name = "lzf"; var gender = "male"; var fn = function(){consol ...
- mybatis的Date类型。
在写select的时候,里面的查询语句.where后面如果jdbcType=DATE没有写的话是 这个形式的. <select id="selectPhoto" parame ...
- Activity 启动模式总结
Activity 启动模式: 1. standard: 默认启动模式,每次启动一个Activity都会重新创建一个实例: 2. singleTop: 栈顶复用模式,新Activity位于任务栈的栈顶, ...