说明:

Dijkstra算法是处理单源最短路径的有效算法,但它局限于边的权值非负的情况,若图中出现权值为负的边,Dijkstra算法就会失效,求出的最短路径就可能是错的。

这时候,就需要使用其他的算法来求解最短路径,Bellman-Ford算法就是其中最常用的一个。

适用条件&范围:

单源最短路径(从源点s到其它所有顶点v);

有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E的有向图);

边权可正可负(如有负权回路输出错误提示);

思想:

  我们规定节点都有一个key值,key值记录的是开始节点到本节点的最小距离,每个节点也都有一个p指针指向他的前驱节点。这里我们规定一个操作叫做松弛操作,我们的算法也是最终基于这个操作的。松弛操作就是去更新key的值。

节点B的key值为8,表示从开始节点到B节点之前的最短估计距离是8,而节点A的key值3,是说从开始节点到A节点最短估计是3,当我们发现这个边时,从A到B的距离比较近,所以我们去更新B的key值,同时把B的前驱节点设置成A。这个过程就是松弛操作。

  我们说的Bellman-Ford算法是最简单的算法,就是从开始节点开始循环每一条边,对他进行松弛操作。最后得到的路径就是最短路径。过程如图:

算法步骤:

1.初始化:将除源点外的所有顶点的最短距离估计值 d[v] ← +∞, d[s] ←0;
2.迭代求解:反复对边集E中的每条边进行松弛操作,使得顶点集V中的每个顶点v的最短距离估计值逐步逼近其最短距离;(运行|v|-1次)
3.检验负权回路:判断边集E中的每一条边的两个端点是否收敛。如果存在未收敛的顶点,则算法返回false,表明问题无解;否则算法返回true,并且从源点可达的顶点v的最短距离保存在 d[v]中。

代码:

#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 0x3f3f3f3f
#define N 1010
int nodenum, edgenum, original; //点,边,起点
typedef struct Edge //边
{
int u, v;
int cost;
} Edge;
Edge edge[N];
int dis[N], pre[N];
bool Bellman_Ford()
{
int ok;
for(int i = ; i <= nodenum; ++i) //初始化,起点本身赋值为0,其余赋值为最大
dis[i] = (i == original ? : MAX);
for(int i = ; i <= nodenum - ; ++i)
{
ok=;
for(int j = ; j <= edgenum; ++j)
if(dis[edge[j].v] > dis[edge[j].u] + edge[j].cost) //松弛(顺序一定不能反)
{
dis[edge[j].v] = dis[edge[j].u] + edge[j].cost;
pre[edge[j].v] = edge[j].u;//这里用来存储路径
ok=;
}
if(ok==) //优化这里,如果这趟没跟新任何节点就可以直接退出了。
break;
}
bool flag = ; //判断是否含有负权回路
for(int i = ; i <= edgenum; ++i)
if(dis[edge[i].v] > dis[edge[i].u] + edge[i].cost)
{
flag = ;
break;
}
return flag;
} void print_path(int root) //打印最短路的路径(反向)
{
while(root != pre[root]) //前驱
{
printf("%d-->", root);
root = pre[root];
}
if(root == pre[root])
printf("%d\n", root);
} int main()
{
scanf("%d%d%d", &nodenum, &edgenum, &original);//输入点边起点,一般起点规定为1
pre[original] = original;//为了输出最短路用的,前驱为本身
for(int i = ; i <= edgenum; ++i)
{
scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].cost);//有向图
}
if(Bellman_Ford())//如果没有负权
for(int i = ; i <= nodenum; ++i) //每个点最短路
{
printf("%d\n", dis[i]);
printf("Path:");
print_path(i);
}
else
printf("have negative circle\n");
return ;
}

最短路之Bellman-Ford算法的更多相关文章

  1. Bellman—Ford算法思想

    ---恢复内容开始--- Bellman—Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数w是边集E的映射.对图G ...

  2. Bellman - Ford 算法解决最短路径问题

    Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力 ...

  3. Dijkstra算法与Bellman - Ford算法示例(源自网上大牛的博客)【图论】

    题意:题目大意:有N个点,给出从a点到b点的距离,当然a和b是互相可以抵达的,问从1到n的最短距离 poj2387 Description Bessie is out in the field and ...

  4. poj1860 bellman—ford队列优化 Currency Exchange

    Currency Exchange Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 22123   Accepted: 799 ...

  5. uva 558 - Wormholes(Bellman Ford判断负环)

    题目链接:558 - Wormholes 题目大意:给出n和m,表示有n个点,然后给出m条边,然后判断给出的有向图中是否存在负环. 解题思路:利用Bellman Ford算法,若进行第n次松弛时,还能 ...

  6. ACM/ICPC 之 最短路径-Bellman Ford范例(POJ1556-POJ2240)

    两道Bellman Ford解最短路的范例,Bellman Ford只是一种最短路的方法,两道都可以用dijkstra, SPFA做. Bellman Ford解法是将每条边遍历一次,遍历一次所有边可 ...

  7. Til the Cows Come Home 最短路Dijkstra+bellman(普通+优化)

    Til the Cows Come Home 最短路Dijkstra+bellman(普通+优化) 贝西在田里,想在农夫约翰叫醒她早上挤奶之前回到谷仓尽可能多地睡一觉.贝西需要她的美梦,所以她想尽快回 ...

  8. 算法学习笔记(三) 最短路 Dijkstra 和 Floyd 算法

    图论中一个经典问题就是求最短路.最为基础和最为经典的算法莫过于 Dijkstra 和 Floyd 算法,一个是贪心算法,一个是动态规划.这也是算法中的两大经典代表.用一个简单图在纸上一步一步演算,也是 ...

  9. 图论算法——最短路径Dijkstra,Floyd,Bellman Ford

    算法名称 适用范围 算法过程 Dijkstra 无负权 从s开始,选择尚未完成的点中,distance最小的点,对其所有边进行松弛:直到所有结点都已完成 Bellman-Ford 可用有负权 依次对所 ...

  10. 蓝桥杯 algo_5 最短路 (bellman,SPFA)

    问题描述 给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环).请你计算从1号点到其他点的最短路(顶点从1到n编号). 输入格式 第一行两个整数n, m. 接下来的m行,每行有三个 ...

随机推荐

  1. 3.sublime vue 语法高亮插件安装

    默认情况下,Vue.js 的单文件组件(*.vue)在 sublime 编辑器中是不被识别的.若要想高亮显示,需要安装插件 Vue Syntax Hightlight.安装步骤如下:   第一,在 s ...

  2. 利用宏定义实现C++程序在Unix和Win32环境下的通用性

    [转] 1.1. 宏定义软件的代码,从跨平台的角度来看,可以分为平台相关的和平台无关的.采用C/C++编写的软件,在进行移植时,平台无关的的代码基本上不需要做大的改动,但平台相关的代码需要做很大的调整 ...

  3. JavaScript从入门到忘记

    JavaScript是一门编程语言,浏览器内置了JavaScript语言的解释器,所以在浏览器上按照JavaScript语言的规则编写相应代码之,浏览器可以解释并做出相应的处理. 一.如何编写 二.变 ...

  4. 微信开发之获取jsapi_ticket

    一.获取流程 1.获取 access_token 2.通过access_token换取 jsapi_ticket 3.签名算法 签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有 ...

  5. MyBatis源码解析【5】工厂的构建

    前言 这个分类比较连续,如果这里看不懂,或者第一次看,请回顾之前的博客 http://www.cnblogs.com/linkstar/category/1027239.html 终于算是把装备弄齐全 ...

  6. MQ的导出备份

    参考链接: http://www.ibm.com/developerworks/cn/websphere/library/techarticles/1312_hub_mq/1312_hub_mq.ht ...

  7. vijos1056题解

    题目: 桌面上放了N个平行于坐标轴的矩形,这N个矩形可能有互相覆盖的部分,求它们组成的图形的面积. 在翻题目时,偶然发现了这道标号为WA的题目. 原来,以前我把一中培训的代码发了上去,却WA了4个点, ...

  8. TortoiseGit上传项目到github方法(超简单)

    Github是咱广大开发者用的非常多的项目版本管理网站,项目托管可以是私人的(private)或者公开的(public),私人的收费,一个月7美金.咱这里就只说我们个人使用的,一般都是代码对外开放的: ...

  9. CentOS7 yum安装zabbix3.2.6

    前言: 本人小白,在一个多月前通过面试进入公司,在进入公司的第一天,老板把我叫到他办公室,坐下来慢慢喝茶,吹牛,给我吹他们以前做的软件,经营的产品,还装作一副什么都告诉我的样子,其实这都是套路,我早已 ...

  10. eclipse打开时提示:failed to create the java virtual machine

    Eclipse打开时提示: failed to create the java virtual machine 原因:C盘空间不够   编辑删除 处理:1.用金山清理临时文件: 2.用金山手机卫士连接 ...