單源點最短路徑
---雨竹清風
單源最短路徑:是從某乙個源點s出發到圖中的所有的頂點之間的最短路徑。
1.單源點最短路徑的變體
:1)單終點最短路徑問題:找到從每乙個頂點到終點的最短路徑。可以將圖中的邊全部反向,然後求單源點最短路徑即可。
2)單對頂點最短路徑問題:對於圖中的兩個頂點u和v,找到從u到v的最短路徑。
3)每對頂點間最短路徑問題:找到圖中的每對頂點之間的最短路徑。
知識點:
①最短路徑的子結構:
引理:最短路徑的子路徑是最短路徑。
這是動態規劃和貪心的演算法。
②負權值邊:
負權值是指邊上的權值是負數,比如罰款。若圖中存在負權迴路,那麼最短路徑的定義就不對了,因為每次經過負權迴路總是能夠得到更小的權值。
③迴路:
最短路徑會包含迴路嗎?最短路徑是不會包含迴路的,不僅不能包含負權迴路,而且是不能包含正權迴路。因為若路徑上存在乙個環,
我們將環移除之後便是一條更短的路徑,所以說一條最短路徑上不可能存在正權環。
④零權迴路:
零權迴路是指路徑上存在乙個環,環的權值是
0,所以可以通過移除零權環路,便得到一條從源點s到
v的一條無環迴路。
2.最段路徑的表示
最短路徑上的頂點是源點可達的頂點的集合。最短路徑樹上的每一條路徑便是從源點到某乙個頂點的最短路徑。[
最短路徑樹
:從源點到源點可達的頂點之間存在一條最短路徑,這些最短路徑便構成了最短路徑樹]
在最短路徑樹上,源點到某乙個頂點之間的唯一的簡單路徑便是從源點到該頂點的最短路徑。
綠色的邊標出的是一棵以源點
v0為根的最短路徑樹。
知識點:
鬆弛技術:
鬆弛表示緊縮上屆的操作,即對於從源點到該結點的最短路徑的修改。若用
d.u,
d.v表示從源點到u,
v的最短路徑
,那麼d.v
≤d.u+w(u,v)
這個不等式必須滿足,這個不等式的約束是比較鬆弛的,所以稱為鬆弛技術。若在鬆弛之前
d.v>d.u+w(u,v)
,那麼經過鬆弛之後,即條件滿足修改
d.v的值,令
d.v = d.u+w(u,v)
,因此d.v
的值會減少。若在鬆弛之前
d.v
≤d.u+w(u,v)
,那麼d.v
不會修改。
3.bellman-ford演算法
解決的問題:bellman-ford演算法能夠在一般的情況(存在負權環路)下,解決單源點最短路徑問題。
bellman-ford演算法將對每一條邊進行鬆弛操作,共進行|v|-1次;本演算法將會返回乙個布林值,布林值的作用是判斷該圖中是否存在負權迴路,若該布林值為false則存在負權迴路,那麼問題無解,否則問題有解。
偽**如下:
為什麼迴圈n-1次即可?
因為最短路徑肯定是個簡單路徑,不可能包含迴路的,如果包含迴路,且迴路的權值和為正的,那麼去掉這個迴路,可以得到更短的路徑。如果迴路的權值是負的,那麼肯定沒有解了,圖有n個點,又不能有迴路,所以最短路徑最多n-1邊。又因為每次迴圈,至少relax一邊,所以最多n-1次就行了。
為什麼還需要進行檢測是否存在負權環?
因為對於圖中的n-1次鬆弛操作並沒***一定沒有負權環,若有負權環,那麼對於圖中進行n-1次鬆弛操作結論依然成立。所以一定要檢測是否存在負權環。
檢測負權環的思想
:將圖中所有的邊進行一次檢測,檢查是否存在(u,v,w)這麼一條邊,使得v.d > u.d + w,若存在則說明會有負權環的存在,所以問題無解。若不存在,那麼有解。
**bellman-ford演算法:
給定乙個鬆弛邊的順序:
(t,x) (t,y) (t,z) (x,t) (y,x) (y,z) (z,x) (z,s) (z,t)
原圖:頂點上的值代表從源結點s到v的最短路徑上權值的上界,初始化為無窮。
單源點最短路徑
include include include using namespace std 自定義比較大小,負數均視為無窮大,其他大小正常 xbool lessthen float x,float y 長度為len的s陣列是否包含e 包含e,return true bool contain int s,...
最短路徑問題(單源點和多源點)
單源點 多源點演算法思想 先初始化距離陣列d inf d 1 0 根據d v min d u w u v d v 對所有的邊進行 鬆弛 值得注意,每一輪鬆弛都會更新至少一條最短路徑,即得到乙個最小的 d i 時間複雜度 o v w bellmanford g,w,s 檢驗是否有負權邊 for u,v...
多源點最短路徑
給出s個起點,給出t個終點,求出所有起點到終點的最短路中的最短的乙個.構建乙個超級源點,與每乙個起點相連,權值為0 構建乙個超級終點,與每乙個終點相連,權值為0。然後求超級源點到超級終點的最短路徑。include includeusing namespace std int first 1010 d...