Bellman-Ford算法的改进:SPFA算法
来源:互联网 发布:剑三大师脸型数据 编辑:程序博客网 时间:2024/05/17 08:40
一、算法简介
SPFA算法全称是最短路径快速算法(Shortest Path Faster Algorithm),是基于Bellman-Ford算法的队列优化。SPFA算法能和Bellman-Ford算法一样,可以处理带负权值边的图,但是复杂度要小很多。
一般认为,此算法的时间复杂度为O(ke),其中k为所有顶尖进队的平均次数,可以证明k一般不超过2。
原来的Bellman-Ford算法,对图进行 |V|-1 次遍历,多了很多没有必要的操作。现在考虑用一个队列来优化,若顶点v的最短路径改变了,则将此顶点入队。下一次遍历从该顶点出发到所有邻接顶点的边,进行松弛操作,也只将更新了最短路径的边入队。
二、伪代码实现
wikipedia的版本
procedure Shortest-Path-Faster-Algorithm(G, s) 1 for each vertex v ≠ s in V(G) 2 d(v) := ∞ 3 d(s) := 0 4 offer s into Q 5 while Q is not empty 6 u := poll Q 7 for each edge (u, v) in E(G) 8 if d(u) + w(u, v) < d(v) then 9 d(v) := d(u) + w(u, v) 10 if v is not in Q then 11 offer v into Q
三、C++实现
/* * @ spfa.cpp * @authorHalfish Zhang * @version1.0 2014/5/24 */#include <iostream>#include <queue>#include <vector>#include <stack>using namespace std;// 最大的顶点数const int MAX_NUM = 2014;// 定义常量无穷大const int INF_NUM = 0x3f3f3f3f;// 用邻接链表来存储边struct Edge{int v;int weight;};// 邻接表用vector来存储比较合适vector<Edge> edges[MAX_NUM * 2];int vertexNum, edgeNum;// 实际的顶点数和边数int source;// 源点int dist[MAX_NUM], pred[MAX_NUM];// dist[i]用来存放从 source 到 i 的最短距离,pred[i]为最短路径的前驱bool inQueue[MAX_NUM]; // inQueue[i]存放顶点 i 是否在队列中int pushCount[MAX_NUM]; // pushCount[i] 表示顶点 i 被放进队列的次数queue<int> q;bool spfa(){// initfor(int i = 1; i <= vertexNum; ++ i){dist[i]= INF_NUM;pred[i] = -1;inQueue[i] = false;pushCount[i] = 0;}dist[source] = 0;// push source into queueq.push(source);inQueue[source] = true;pushCount[source] = 1;while(!q.empty()){// cur means current vertexint curr = q.front();q.pop();inQueue[curr] = false;// edges[curr]是一个vector,里面放着和curr相邻的边Edge。 int len = edges[curr].size();//共len个顶点与curr相邻for(int i = 0; i < len; ++ i){Edge *edges_vec = &edges[curr][i]; // 用edges_vec表示第i条边,便于寻址// 松弛操作 relaxif(dist[(*edges_vec).v] > dist[curr] + (*edges_vec).weight ){dist[(*edges_vec).v] = dist[curr] + (*edges_vec).weight;pred[(*edges_vec).v] = curr;// 若不在队列中,需要加入队列if(!inQueue[(*edges_vec).v]){q.push((*edges_vec).v);inQueue[(*edges_vec).v] = true;pushCount[(*edges_vec).v] ++;// 如果入队列的次数超过vertexNum,说明存在负权值cycleif(pushCount[(*edges_vec).v] > vertexNum){// 释放内存?while(!q.empty()) {q.pop();}return false;}}}}}return true;}void print(int i){cout << "The path from " << source << " to " << i << " is : " << endl;stack<int> s;s.push(i);while(s.top() != source) {s.push(pred[s.top()]);}int len = s.size();for(int i = 0; i < len; ++ i) {cout << s.top() << " ";s.pop();}cout << endl << endl;}int main(int argc, char const *argv[]){cout << "Please input the vertexNum, edgeNum and source:" << endl;cin >> vertexNum >> edgeNum >> source;cout << "Please input the " << edgeNum ;cout << " edges, which from u to v with weight of w" << endl;int u1, v1, w1;Edge temp;for(int i = 0; i < edgeNum; ++ i) {cout << i + 1 << " : ";cin >> u1 >> v1 >> w1;temp.v = v1;temp.weight = w1;edges[u1].push_back(temp);}if( spfa() ){cout << endl << endl;cout << "The minimum weight of these paths from " << source << " are: " << endl;for(int i = 1; i <= vertexNum; ++ i)cout << dist[i] << " ";cout << endl << endl;cout << "All these paths are as follows: " << endl;for(int i = 1; i <= vertexNum; ++ i)print(i);} else {cout << "Sorry, no shortest path exist, ";cout << "because there are some nagetive cycles" << endl;}return 0;}
四、测试样例
见下图
输入样例:
6 9 1
1 2 7
1 3 9
1 6 14
2 3 10
2 4 15
3 4 11
3 6 2
4 5 6
5 6 9
输出样例
The minimum weight of these paths from 1 are:
0 7 9 20 26 11
All these paths are as follows:
The path from 1 to 1 is :
1
The path from 1 to 2 is :
1 2
The path from 1 to 3 is :
1 3
The path from 1 to 4 is :
1 3 4
The path from 1 to 5 is :
1 3 4 5
The path from 1 to 6 is :
1 3 6
--------------------------------
Process exited with return value 0
Press any key to continue . . .
- Bellman-Ford算法的改进:SPFA算法
- Bellman-Ford&SPFA算法
- bellman-ford算法的优化spfa算法
- 转:Bellman-Ford算法及其改进---SPFA算法
- Bell-Ford 算法的改进--SPFA算法
- 松弛算法-->Bellman-Ford-->SPFA
- Bellman-ford和spfa算法
- Bellman-ford和spfa算法
- Bellman-Ford算法 和 SPFA算法
- Bellman-ford算法学习与SPFA算法
- Bellman-ford队列优化算法 SPFA算法
- SPFA算法 (基于Bellman-Ford算法)
- SPFA算法模板(实际上是bellman-ford) 的队列优化
- Bellman-Ford算法以及优化(SPFA)
- Bellman-Ford 算法及其优化以及SPFA
- 最短路算法 Dijkstra Bellman-Ford SPFA
- Dijkstra、Bellman-ford、SPFA、Floyd算法
- 单源最短路径--Bellman-Ford算法及SPFA
- 设计模式之状态模式
- nginx源码分析--模块分类
- Silerlight调用WCF、Web Service、Wcf Ria Service跨域的问题
- OCP-1Z0-051 第169题 使用子查询DELETE数据
- OCP 1Z0 051 117
- Bellman-Ford算法的改进:SPFA算法
- 关于父类没有缺省的构造函数时,子类如何建立构造函数
- cocos2dx中的box2d
- python实现的一个简单的文本解析工具,用于解析类xml格式(不带标签属性、标签不嵌套)
- 黑马程序员_java的反射与内省
- 软件架构与数据结构
- 浏览器也郁闷了,来吐个槽
- xcode 5.1.1 storyBoard 在二级页面写按钮不崩溃的方法
- ZOJ 3468 Dice War