Bellman-Ford算法
来源:互联网 发布:在线运行js代码 编辑:程序博客网 时间:2024/05/17 20:30
一、算法概述
- Bellman-Ford算法,也可以翻译成中文“贝尔曼-福特算法”,常常拿来和Dijkstra算法一起比较理解。
- Bellman-Ford算法的原理是对图进行 V-1 次松弛操作,算法的复杂度高达O(VE)。但是相对于Dijkstra算法,尽管算法复杂度稍高一些,但是它能处理带负权值边而没有负权回路的图。V-1次松弛操作,必定能求出最短路径,因为图的深度最多为V-1.
二、实现步骤
- 数组 distance[v] 表示从源点source到顶点v的最短路径,即为要求的答案。
- 数组 predecessor[v] 表示从源点source到顶点v的最短路径p(s,....,v),顶点v的前一个节点。可以由此数组导出一个前驱子图或以source为根的最短路径树。
- w表示边 (u,v) 的权值。
- 初始化操作:一开始从source到自己的距离为0,到其他所有点的最短距离为正无穷大。
- 进行 V-1 次松弛操作:每一次对所有的边遍历一遍,若distance[u] + w < distance[v],则更新distance[v]和predecessor[v]。
- 检查是否存在负权回路:对每条边遍历一遍,若仍然可以更新distance,说明存在负权回路。
三、伪代码实现
摘自维基百科的贝尔曼-福特算法中文词条。其中的过程可以改写成带布尔型变量返回值的函数。若存在负权回路,则返回false,否则返回true。distance和predecessor可以设置为全局变量。
procedure BellmanFord(list vertices, list edges, vertex source) // 该实现读入边和节点的列表,并向两个数组(distance和predecessor)中写入最短路径信息 // 步骤1:初始化图 for each vertex v in vertices: if v is source then distance[v] := 0 else distance[v] := infinity predecessor[v] := null // 步骤2:重复对每一条边进行松弛操作 for i from 1 to size(vertices)-1: for each edge (u, v) with weight w in edges: if distance[u] + w < distance[v]: distance[v] := distance[u] + w predecessor[v] := u // 步骤3:检查负权环 for each edge (u, v) with weight w in edges: if distance[u] + w < distance[v]: error "图包含了负权环"
注意这里是有向图的实现。顶点是从1开始的,所以下面的代码中有三处的for循环是从1开始而非0;
/* * Bellman-Ford.cpp * Author: Halfish Zhang * Creat_Time: 5/19/2014 */#include <iostream>#include <stack>using namespace std;const int INF_NUM = 0x3f3f3f3f; // momerize this constconst int N = 2014;struct Edge{int u, v;// edge (u,v)int weight; // the cost(or weight) of edge (u,v)};int vertexNum, edgeNum, source;int distances[N], predecessor[N];Edge edges[N];bool Bellman_Ford(){cout << "Bellman_Ford called" << endl;// Step One: initializefor(int i = 1; i <= edgeNum; ++ i){distances[i] = INF_NUM; // you can also use "memset(distances, 0x3f, edgeNum)" to initialize;predecessor[i] = i;}distances[source] = 0;// Step Two: relaxation technique, complexity is O(VE)for(int i = 1; i <= vertexNum - 1; ++ i){for(int j = 0; j < edgeNum; ++ j){if(distances[edges[j].v] > distances[edges[j].u] + edges[j].weight){// update distances and predecessordistances[edges[j].v] = distances[edges[j].u] + edges[j].weight;predecessor[edges[j].v] = edges[j].u;}}}// Step Three: check if the cycle with nagative weight exists bool flag = true;for(int i = 0; i < edgeNum; ++ i){if(distances[edges[i].v] > distances[edges[i].u] + edges[i].weight){flag = false;break;}}return flag;}void print_shortest_path(int destination) {cout << "print_shortest_path called" << endl;stack<int> s;s.push(destination);while(predecessor[s.top()] != source){s.push(predecessor[s.top()]);}s.push(source);cout << "The Path of ( " << source << ", " << destination << " ) is: " << endl; int len = s.size();for(int i = 0; i < len; ++ i) {cout << s.top() << " ";s.pop();}cout << endl;}int main(int argc, char const *argv[]){cin >> vertexNum >> edgeNum >> source;for(int i = 0; i < edgeNum; ++ i) {cin >> edges[i].u >> edges[i].v >> edges[i].weight;} if ( Bellman_Ford() ) {//test_print();for(int i = 0; i < vertexNum; ++ i){//attention: edges are numbered 1...Nprint_shortest_path(i+1);}} else {cout << "Sorry, a cycle with negative weight exists!";}return 0;}
五、样例
见下图:
输入样例
6 9 11 2 71 3 91 6 142 3 102 4 153 4 113 6 24 5 65 6 9
输出样例
Bellman_Ford calledprint_shortest_path calledThe Path of ( 1, 1 ) is:1 1print_shortest_path calledThe Path of ( 1, 2 ) is:1 2print_shortest_path calledThe Path of ( 1, 3 ) is:1 3print_shortest_path calledThe Path of ( 1, 4 ) is:1 3 4print_shortest_path calledThe Path of ( 1, 5 ) is:1 3 4 5print_shortest_path calledThe Path of ( 1, 6 ) is:1 3 6--------------------------------Process exited with return value 0Press any key to continue . . .
0 0
- Bellman-Ford&SPFA算法
- Bellman-ford算法实现
- Bellman-Ford 算法详解
- Bellman-Ford算法
- Bellman-Ford算法
- Bellman-Ford路由算法
- Bellman-Ford算法分析
- bellman ford算法
- Bellman-Ford算法
- Bellman-Ford算法总结
- Bellman-ford算法
- bellman-ford算法
- bellman-ford 算法
- Bellman-Ford算法
- Bellman-Ford算法
- bellman ford 算法
- Bellman-Ford 算法
- Bellman-Ford算法
- leetcode:path sum(I) 递归与非递归解法
- PADS中创建不规则焊盘
- STL之全排列
- Android代码混淆
- undefined reference问题总结
- Bellman-Ford算法
- System V信号量(1)
- ajax开发
- 媲美韩寒 上海传智学员佳作《钥匙》
- SQL Server COUNT() 和SUM()的使用方法
- Android 数据存储 之 SQLite数据库详解
- Oracle基础知识笔记(12) 集合、序列
- hadoop ha CDH5.01 , 两个NN都是standby
- mysql查询统计