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算法详解的更多相关文章

  1. 图的最短路径-----------SPFA算法详解(TjuOj2831_Wormholes)

    这次整理了一下SPFA算法,首先相比Dijkstra算法,SPFA可以处理带有负权变的图.(个人认为原因是SPFA在进行松弛操作时可以对某一条边重复进行松弛,如果存在负权边,在多次松弛某边时可以更新该 ...

  2. SPFA 算法详解

    适用范围:给定的图存在负权边,这时类似Dijkstra等算法便没有了用武之地,而Bellman-Ford算法的复杂度又过高,SPFA算法便 派上用场了. 我们约定有向加权图G不存在负权回路,即最短路径 ...

  3. SPFA 算法详解( 强大图解,不会都难!) (转)

    适用范围:给定的图存在负权边,这时类似Dijkstra等算法便没有了用武之地,而Bellman-Ford算法的复杂度又过高,SPFA算法便 派上用场了. 我们约定有向加权图G不存在负权回路,即最短路径 ...

  4. SPFA算法详解

    前置知识:Bellman-Ford算法 前排提示:SPFA算法非常容易被卡出翔.所以如果不是图中有负权边,尽量使用Dijkstra!(Dijkstra算法不能能处理负权边,但SPFA能) 前排提示*2 ...

  5. Bellman-Ford算法与SPFA算法详解

    PS:如果您只需要Bellman-Ford/SPFA/判负环模板,请到相应的模板部分 上一篇中简单讲解了用于多源最短路的Floyd算法.本篇要介绍的则是用与单源最短路的Bellman-Ford算法和它 ...

  6. 【最短路径Floyd算法详解推导过程】看完这篇,你还能不懂Floyd算法?还不会?

    简介 Floyd-Warshall算法(Floyd-Warshall algorithm),是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似.该算法名称以 ...

  7. BM算法  Boyer-Moore高质量实现代码详解与算法详解

    Boyer-Moore高质量实现代码详解与算法详解 鉴于我见到对算法本身分析非常透彻的文章以及实现的非常精巧的文章,所以就转载了,本文的贡献在于将两者结合起来,方便大家了解代码实现! 算法详解转自:h ...

  8. kmp算法详解

    转自:http://blog.csdn.net/ddupd/article/details/19899263 KMP算法详解 KMP算法简介: KMP算法是一种高效的字符串匹配算法,关于字符串匹配最简 ...

  9. 机器学习经典算法详解及Python实现--基于SMO的SVM分类器

    原文:http://blog.csdn.net/suipingsp/article/details/41645779 支持向量机基本上是最好的有监督学习算法,因其英文名为support vector  ...

随机推荐

  1. nginx各版本全自动编译安装脚本

    #!/bin/bash #作者:星云法师(头条号:西西图图---专注美食领域的研究) #环境:centos7,如果是其它的系统可以相应做调整.#--------选择安装方式,网络晚装还是本地安装--- ...

  2. 【新手向】一个超简单的jquery.mCustomScrollbar滚动条插件Demo

    <script src="https://cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script> < ...

  3. vue.js(7)--vue中的样式绑定

    vue中class样式与内联样式的绑定 <!DOCTYPE html> <html lang="en"> <head> <meta cha ...

  4. Solr的学习使用之(四)建数据库(添加Core)、表(配置schema.xml)

    1.数据库数据库就相当于solr里面的核.solr4.6不能使用界面提供的的Core Admin/Add Core来建立,会报错,不懂为啥:那就采用最 简单的办法:把solr下载包里面的\solr-4 ...

  5. 数据库系统实现 第一章 DBMS实现概述

    DBMS提供的能力 1)持久存储 DBMS在灵活性方面比文件系统要好,同时支持对非常大量数据的存储 2)编程接口 3)事务管理 DBMS支持对数据的并发存取,即多个不同的进程(称作事物)同时存取操作, ...

  6. 【LeetCode】字符串 string(共112题)

    [3]Longest Substring Without Repeating Characters (2019年1月22日,复习) [5]Longest Palindromic Substring ( ...

  7. 【LeetCode】贪心 greedy(共38题)

    [44]Wildcard Matching [45]Jump Game II (2018年11月28日,算法群衍生题) 题目背景和 55 一样的,问我能到达最后一个index的话,最少走几步. 题解: ...

  8. 【LeetCode】一种博弈思路 minimax(共5题)

    [292] Nim Game (2019年3月12日,E) 有一堆石头,游戏规则是每次可以从里面拿1-3颗石头,拿到最后的石头的人赢.你和你的对手都 optimal 的玩这个游戏,问先手(也就是你)能 ...

  9. [BZOJ2341][Shoi2011]双倍回文 manacher+std::set

    题目链接 发现双倍回文串一定是中心是#的回文串. 所以考虑枚举#点.发现以\(i\)为中心的双倍回文的左半部分是个回文串,其中心一定位于\(i-\frac{pal[i]-1}2\)到\(i-1\)之间 ...

  10. C#基础提升系列——C#任务同步

    C#任务同步 如果需要共享数据,就必须使用同步技术,确保一次只有一个线程访问和改变共享状态.如果不注意同步,就会出现争用条件和死锁. 不同步导致的线程问题 如果两个或多个线程访问相同的对象,并且对共享 ...