spfa的算法思想(動態逼近法):
設立一個先進先出的隊列q用來保存待優化的結點,優化時每次取出隊首結點u,並且用u點當前的最短路徑估計值對離開u點所指向的結點v進行松弛操作,如果v點的最短路徑估計值有所調整,且v點不在當前的隊列中,就將v點放入隊尾。這樣不斷從隊列中取出結點來進行松弛操作,直至隊列空為止。
松弛操作的原理是著名的定理:“三角形兩邊之和大於第三邊”,在信息學中我們叫它三角不等式。所謂對結點i,j進行松弛,就是判定是否dis[j]>dis[i]+w[i,j],如果該式成立則將dis[j]減小到dis[i]+w[i,j],否則不動。
下面舉一個實例來說明SFFA算法是怎樣進行的:


和廣搜bfs的區別:
SPFA 在形式上和廣度(寬度)優先搜索非常類似,不同的是bfs中一個點出了隊列就不可能重新進入隊列,但是SPFA中一個點可能在出隊列之后再次被放入隊列,也就是一個點改進過其它的點之后,過了一段時間可能本身被改進(重新入隊),於是再次用來改進其它的點,這樣反復迭代下去。
算法的描述:
void spfa(s); //求單源點s到其它各頂點的最短距離 for i=1 to n do { dis[i]=∞; vis[i]=false; } //初始化每點到s的距離,不在隊列 dis[s]=0; //將dis[源點]設為0 vis[s]=true; //源點s入隊列 head=0; tail=1; q[tail]=s; //源點s入隊, 頭尾指針賦初值 while head<tail do { head+1; //隊首出隊 v=q[head]; //隊首結點v vis[v]=false; //釋放對v的標記,可以重新入隊 for 每條邊(v,i) //對於與隊首v相連的每一條邊 if (dis[i]>dis[v]+a[v][i]) //如果不滿足三角形性質 dis[i] = dis[v] + a[v][i] //松弛dis[i] if (vis[i]=false) {tail+1; q[tail]=i; vis[i]=true;} //不在隊列,則加入隊列 }