SPFA算法:求单源最短路的SPFA算法的全称是:Shortest Path Faster Algorithm,是Bellman-Ford算法0(VE)的一个优化,期望的时间复杂度O(2E),E为图的边数,所以SPFA用在稀疏图上的效果会更加明显。SPFA对Bellman-Ford算法优化的关键之处在于意识到:只有那些在前一遍松弛中改变了距离估计值的点,才可能引起他们的邻接点的距离估计值的改变。
很多时候,给定的图存在负权边,这时类似Dijkstra算法(0(V^2),在稠密图上有优势)便没有了用武之地,而bellman_ford的复杂度又过高,SPFA算法便派上用场了。
算法核心思想:理解这个算法,最好先看看Bellman-Ford,因为他是对Bellman-Ford的一个优化,SPFA算法采用了一个队列,优化算法,用数组dict[]记录每个结点的最短路径估计值,而且用邻接表来存储图G。我们采取的方法是动态逼近法:设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点放入队尾。这样不断从队列中取出结点来进行松弛操作,直至队列空为止。
需要注意的是:仅当图不存在负权回路时,SPFA能正常工作。如果图存在负权回路,由于负权回路上的顶点无法收敛,总有顶点在入队和出队往返,队列无法为空,这种情况下SPFA无法正常结束。
1 记录每个结点进队次数,超过|V|次表示有负权
2 记录这个结点在路径中处于的位置,ord[i],每次更新的时候ord[i]=ord[x]+1,若超过|V|则表示有负圈....
下面举一个实例来说明SFFA算法是怎样进行的:
算法执行时各步的Queue队的值和D数组的值由下表所示:
算法执行到第五步后,队Queue空,算法结束。源点V0到V1的最短路径为2,到V2的最短路径为5,到V3的最短路径为9,到V4的最短路径为9,结果显然是正确的。
SPFA算法模板1:(邻接矩阵)
const int nMax = 1000;
const int eMax = 2000;
const int inf = 0xffffff;
int n, edge[nMax][nMax], dict[nMax];
int queue[eMax];
bool vis[nMax];
void init_data(s){
}
void spfa(int s){
}
SPFA算法模板2:(邻接表)
#include<iostream>
using namespace std;
#define MAXE 10000
#define MAXV 1000
int inf = 1000000000;
struct edge_t
{
};
edge_t arrEdge[MAXE]; //arrEdge[1...szEdge]保存szEdge条边.
int szEdge;
int arrHead[MAXV];
int nv;
int arrPre[MAXV];
int arrDis[MAXV];
int Que[MAXE*10]; //队列
char inQue[MAXV]; //点v是否在队列中
void SPFA(int s)
{
}
int main()
{
}


被折叠的 条评论
为什么被折叠?



