最短路径——SPFA算法
来源:互联网 发布:数据近义词 编辑:程序博客网 时间:2024/05/23 19:56
关于SPFA(Shortest Path Faster Algorithm)算法,网上的实现与叙述已经有很多,所以在这里也不多说,在NOCOW上面有详细述说。
这个算法是对Bellman_Ford算法的一个队列优化,减少冗余计算。在计算带有负值边的图的最短路问题时是非常好的选择,当然在差分约束系统问题中也是首选。
这个算法的一个特点是,每个顶点可以进队不仅一次,在图中存在负权回路的时候,在该回路上的顶点入队次数会超过顶点总数,这也是判断图中是否存在负权回路的条件。
下面的算法是利用双端队列对一般的SPFA进行SLF优化的实现代码(SLF:Small Label First 策略,设要加入的节点是j,队首元素为i,若dist(j)<dist(i),则将j插入队首,否则插入队尾。)
未优化的SPFA算法伪码如下
Procedure SPFA; Begin initialize-single-source(G,s); initialize-queue(Q); enqueue(Q,s); while not empty(Q) do begin u:=dequeue(Q); for each v∈adj[u] do begin tmp:=d[v]; relax(u,v); if (tmp<>d[v]) and (not v in Q) then enqueue(Q,v); end; end;End;
下面是利用邻接表为存储结构,对SPFA进行SLF优化,并可以判断是否存在负权回路的C++实现
#include <iostream>#include <deque>#include <stack>#include <vector>using namespace std;#define MAXN 100#define INF 99999999struct edge{int to;int weight;};vector <edge> adjmap[MAXN]; //邻接表bool in_queue[MAXN]; //顶点是否在队列中int in_sum[MAXN]; //顶点入队次数int dist[MAXN]; //源点到各点的最短路径int path[MAXN]; //存储到达i的前一个顶点int nodesum; //顶点数int edgesum; //边数bool SPFA(int source){deque <int> dq;int i,j,x,to;for(i=1;i<=nodesum;i++){in_sum[i]=0;in_queue[i]=false;dist[i]=INF;path[i]=-1;}dq.push_back(source);in_sum[source]++;dist[source]=0;in_queue[source]=true;//初始化完成while(!dq.empty()){x=dq.front();dq.pop_front();in_queue[x]=false;for(i=0;i<adjmap[x].size();i++){to=adjmap[x][i].to;if((dist[x] < INF)&&(dist[to] > dist[x]+adjmap[x][i].weight)){dist[to]=dist[x]+adjmap[x][i].weight;path[to]=x;if(!in_queue[to]){in_queue[to]=true;in_sum[to]++;if(in_sum[to] == nodesum)return false;if(!dq.empty()){if(dist[to] > dist[dq.front()])dq.push_back(to);elsedq.push_front(to);}elsedq.push_back(to);}}}}return true;}void Print_Path(int x){stack <int> s;int w=x;while(path[w] != -1){s.push(w);w=path[w];}cout<<"顶点 1 到顶点 "<<x<<" 的最短路径长度为:"<<dist[x]<<endl;cout<<"所经过的路径为:1 ";while(!s.empty()){cout<<s.top()<<" ";s.pop();}cout<<endl;}int main(){int i,s,e,w;edge temp;cout<<"输入顶点数和边数:";cin>>nodesum>>edgesum;for(i=1;i<=nodesum;i++)adjmap[i].clear(); //清空邻接表for(i=1;i<=edgesum;i++){cout<<"输入第 "<<i<<" 条边的起点、终点还有对应的权值:";cin>>s>>e>>w;temp.to=e;temp.weight=w;adjmap[s].push_back(temp);}if(SPFA(1)){for(i=2;i<=nodesum;i++)Print_Path(i);}elsecout<<"图中存在负权回路"<<endl;return 0;}
下面是两个测试,第一个生成的图是和Bellman_Ford算法中的测试数据一样的,这里就不再给出该图,可以通过连接去该文章中查看。
第二个测试是具有负权回路的图
下面是第二个测试的图,将其中顶点s编号为1,其余顶点的编号按照字母顺序编号。
- 最短路径——SPFA算法
- SPFA算法——最短路径
- SPFA算法——最短路径
- spfa算法——最短路径算法
- 最短路径算法---SPFA
- 最短路径----SPFA算法
- 【最短路径】SPFA算法
- SPFA算法【最短路径】
- 最短路径SPFA算法
- 最短路径——SPFA
- 最短路径——SPFA
- 最短路径算法之SPFA算法
- POJ_2394_最短路径---SPFA算法
- 最短路径之SPFA算法
- 最短路径 之 SPFA算法
- 最短路径的SPFA算法
- 【转载】最短路径之SPFA算法
- 最短路径问题 SPFA算法
- Android基础之BroadcastReceiver(待完善)
- ALSA音频编程自我分析
- 如果你扯了团队后腿,你应该内疚
- 单片机学习六大要素
- 搜索算法 书籍
- 最短路径——SPFA算法
- java的web配置文件的“<load-on-startup>的说明
- linux mysql
- Vim的行号、语法显示等设置,即.vimrc文件的配置
- Puppy Linux U盘安装使用
- 嵌入式关系型数据库SQLite
- 信息管理系统开发利器-配置实现
- 栈---链表实现
- 关于Iframe的onfocus,IE5~8