SPFA 最短路問題

2021-07-04 17:21:55 字數 1407 閱讀 1091

簡單的說,spfa就是通過佇列·來實現的求最短路徑的演算法;

首先,要用到乙個鄰接表來儲存各頂點之間的關係(包括起點u,終點v,以及u,v之間的權值w)。然後就是構造spfa函式;

第一步:對dis[ ](  用來存從源點到各頂點的最短距離 )初始化為 inf(乙個很大的數例如0x3f3f3f3f), 對 vis[ ]陣列初始化為零(表示未有點入佇列);

構造乙個佇列  queue< int >q;並將源點 s加入佇列;dis[s] = 0( 表示源點本身到本身的距離為零);vis[s] =1(表示源點進入佇列)

第二步:從源點開始找到其他各點的最短路徑,找到與源點相連的點的邊對其進行鬆弛操作*(即當< s,v> 的距離大於+ 的距離時,將d[v]更新為+的距離)

當頂點v未入佇列就將其加入隊尾並標記為1,然後仍是取隊頭元素,以其為新的源點繼續進行鬆弛->更新的操作;直到隊列為空;

(注意,每次取對頭元素時要將對頭元素取消標記即令vis[u]  = 0,)

另外,spfa的另乙個好處就是來求含有負權值圖的最短路徑問題(前提圖中不存在負權迴路,);

還有就是當1、2兩點有重邊時;用spfs不用判重;因為1->2和2->1屬於不同的鄰接表中;(頂點不一樣)

當圖中含有負權迴路時,不存在最短路徑(因為有負權迴路,它將能無限最短);也就有無限次出對入隊,判斷它的方法就是看圖中的點入隊的次數如果大於圖中含有的頂點總數n的話,說明圖中存在負權迴路;

spfa模板:

以杭電2544《最短路》為例:

#include #include #include #include #include #include #define maxn 100+10//點數

#define maxm 20000+10//邊數

#define inf 0x3f3f3f

using namespace std;

struct edge

;edge edge[maxm];

int head[maxn], edgenum;

int n, m;

void addedge(int u, int v, int w)

; edge[edgenum] = e;

head[u] = edgenum++;

}void init()

int dist[maxn]; //儲存源點 到這個點的最短路

int vis[maxn]; //表示這個點是否在佇列裡面

//int used[maxn]; //記錄乙個點 入隊多少次

void spfa(int sx) //sx為源點}}

}printf("%d\n", dist[n]);

}void getmap()

}int main()

return 0;

}

十七 最短路徑問題(SPFA)

spfa演算法 spfa演算法全稱是shortest path faster algorithm。dijkstra不能解決負權邊,bellman ford演算法效率底,可使用spfa演算法。與dijkstra演算法和bellman ford演算法一樣,用陣列d記錄每個節點的最短路長估計,並且用鄰接表...

Spfa演算法 最短路徑問題

spfa原理 設立乙個先進先出的佇列用來儲存待優化的結點,優化時每次取出隊首結點u,並且用u點當前的最短路徑估計值對離開u點所指向的結點v進行鬆弛操作,如果v點的最短路徑估計值有所調整,且v點不在當前的佇列中,就將v點放入隊尾。這樣不斷從佇列中取出結點來進行鬆弛操作,直至佇列空為止。spfa演算法實...

最短路 spfa (一)

最短路 spfa 首先建立起始點a到其餘各點的 最短路徑 首先源點a入隊,當佇列非空時 隊首元素a 出隊,對以a為起始點的所有邊的終點依次進行鬆弛操作 此處有b,c,d三個點 此時路徑 狀態為 在鬆弛時三個點的最短路徑估值變小了,而這些點佇列中都沒有出現,這些點 需要入隊,此時,佇列中新入隊了三個結...