spfa很像bfs
(1)起點s入隊,計算它所有鄰居到s的最短距離(當前最短距離,不是全域性最短距離,把計算乙個節點到s的最短路徑稱為更新狀態)。把s出隊,狀態有更新的節點入隊。也就是說佇列中只處理更新的節點,其他節點無影響不處理。
(2)現在佇列頭部是s的乙個鄰居u。彈出u,更新其他所有鄰居的狀態,把其中有變化的節點入隊。
(3)這裡要注意後面計算中u可能還會更新,因此只要節點狀態有變化,就可以入隊處理。
(4)繼續上述過程,直到隊列為空。
但是spfa的穩定性是不穩定的,可能只有很少的節點重複入隊也可能有很多。競賽中常用spfa的不穩定性卡spfa,因此沒有負權節點時優先使用較穩定的dijkstra
spfa模板(鄰接表+佇列)
洛谷 p3371 【模板】單源最短路徑(弱化版)
#include
using
namespace std;
#define n 500001
const
int inf = int_max;
using
namespace std;
struct edge
;vector e[n]
;//e[i]:存第i個節點連線的所有邊
queue<
int> q;
bool vis[n]
;int n, m, s;
long
long dis[n]
;void
spfa()
//初始化
q.push
(s);
//初始邊入隊
vis[s]
=true
; dis[s]=0
;while
(!q.
empty()
)}}}
}int
main()
);//有向圖
}spfa()
;for
(int i =
1; i <= n; i++
) cout << dis[i]
<<
" ";
return0;
}
dijkstra用了貪心的思想,因此不能處理負邊權,穩定而高效。
程式的主要內容是維護兩個集合,即已確定最短路徑的節點集合a,這些節點向外擴散的鄰居節點集合b。
程式思路如下:
(1)把起點s放到a中,把s所有的鄰居放到b中。此時,鄰居到s的距離就是直連距離。
(2)從b中找到距離起點s最短的節點u,放到a中。
(3)把u所有的新鄰居放到b中。顯然,u的每一條邊都連線了乙個鄰居,每個新鄰居都要加進去。其中u的乙個新鄰居v,它到s的距離dis(s,v)等於dis(s,u)+dis(u,v)。
(4)重複(2)(3),直到b為空時結束。
dijkstra模板(堆優化版鄰接表+優先佇列)
洛谷 p4779 【模板】單源最短路徑(標準版)
#include
using
namespace std;
const
int inf = int_max;
const
int n =
200005
;struct edge};
vector e[n]
;//e[i]:存第i個節點連線的所有邊
struct node
bool
operator
<
(const node &a)
const};
int n, m, s;
void
djk(
)//初始化
dis[s]=0
; priority_queue v;
v.push
(node
(s,0))
;while
(!v.
empty()
)}}for
(int i =
1; i <= n;i++
) cout << dis[i]
<<
" ";
}int
main()
djk();
return0;
}
Dijkstra 單源最短路徑
演算法思想 輔助陣列dis i 表示當前源頂點到i的最短路徑。dis i 在程式未結束前,類似於動態規劃,可更新以取得最小值 陣列path用來記錄路徑 首先初始化令dis i 為edge v0 i v0為源頂點 然後選擇離源頂點最小的路徑,加入到構造最短路徑的點集合中,然後看是否可以更新dis i ...
Dijkstra 單源最短路徑
演算法思想 輔助陣列dis i 表示當前源頂點到i的最短路徑。dis i 在程式未結束前,類似於動態規劃,可更新以取得最小值 陣列path用來記錄路徑 首先初始化令dis i 為edge v0 i v0為源頂點 然後選擇離源頂點最小的路徑,加入到構造最短路徑的點集合中,然後看是否可以更新dis i ...
Dijkstra單源最短路徑
dijkstra單源最短路徑 給定乙個帶權有向圖g v,e 其中每條邊的權是乙個非負實數。另外,還給定 v 中的乙個頂點,稱為源。現在我們要計算從源到所有其他各頂點的最短路徑長度。這裡的長度是指路上各邊權之和。這個問題通常稱為單源最短路徑問題。下面給出兩個計算單源最短路徑的模板。dijkstra 簡...