Bellman Ford演算法求最短路

2021-08-21 23:38:01 字數 1383 閱讀 1373

圖論中比較基礎的問題,求單源最短路,即在圖中找乙個點作為起點,求他到其他點的最短路,而bellman-ford演算法是其中最簡單的演算法,相應地,其複雜度也比較高,效率也比較低,但是,他卻可以判斷圖中是否存在負權迴路(走一圈經過的權值是負數),因此可以處理帶有負權邊的圖,且該演算法是其他各種最短路演算法的原始型,應當受到足夠的重視。

設有圖g< v, e >,點數為v,邊數為e,源點為s點。我們用乙個distance陣列(下寫為dis陣列)來記錄各點到s點的最短距離,將其初始化為inf(一般是個很大的常數),dis[s] = 0。

演算法的基本思路是一種動態逼近的思想:

很顯然,如果我們知道一條邊起點到源點的最短距離和這條邊的邊權,那麼終點到s點的最短距離為起點到源點的最短距離+邊權,即 dis[終點] = dis[起點]+邊權。

據此,我們執行v-1次對每一條邊的鬆弛操作:對於該邊,如果dis[起點]+邊權 < dis[終點],則將dis[終點]變為dis[起點]+邊權。

為什麼是v-1次呢?

假如是第一次對所有邊進行鬆弛操作,dis一開始被初始化為inf,所以那些s點直接相連的點,他們的dis會更新,他們與s點之間的邊的鬆弛是有效的;

而其他的點,他們不與s點直接相連,那麼對於所有與這些點有關的邊,他們起點的初始dis值與終點的初始dis值均為inf,所以鬆弛條件不滿足,無法鬆弛。

第二次時,所有與源點直接相連的點的dis值都是有效的,按第一次同樣的原理,所有與這些點直接相連的點的dis值被有效更新,dis值有效的範圍在經過兩次對所有邊的鬆弛之後,以源點為根樹狀地擴充套件了兩層,所有與s點小於等於兩條邊相連的點的dis值被有效更新。

於是我們知道,在g圖中,乙個點最壞情況和s點之間有v-1條邊,所以至多我們進行v-1此對所有邊的鬆弛操作即可得出圖中任何一點到s點的最短路。

如果有邊,其邊權為負值,那麼其dis[起點]+邊權 恆小於 dis[終點],則對其的鬆弛永遠都能進行。所以我們可以再進行一次(即第v次)對所有邊的鬆弛操作,邊集中若無負邊權,則各點dis值均為最短路,無法滿足鬆弛條件,若存在負邊權,則此邊鬆弛條件依然是滿足的,可據此判斷出存在負邊權。

偽**過程:

宣告圖g , 陣列dis, 源點s;

for(i = 1 to v) dis[i] = inf;

dis[s] = 0;

for(i = 1 to v-1)

foreach 邊∈g

if(dis[起點]+邊權 < dis[終點])

dis[終點] = dis[起點] + 邊權;

宣告 flag = true; //若flag為false代表g中存在負邊權

foreach 邊∈g

if(dis[起點]+邊權 < dis[終點])

flag = false;

最終dis[n]為n點到s點的最短路距離。

Bellman Ford演算法(求單源最短路徑)

struct edgenode edgenode int x,int w num x weigh w next nullptr bellman ford演算法 o e v 複雜度,用來求解單源最短路徑 從某個起點s到達所有其它節點的最短路徑 bool bellman ford vector vert...

Bellman Ford演算法,SPFA演算法

bellman ford 演算法能在更普遍的情況下 存在負權邊 解決單源點最短路徑問題。對於給定的帶權 有向或無向 圖g v,e 其源點為 s,加權函式w是 邊集e 的對映。對圖g執行 bellman ford 演算法的結果是乙個布林值,表明圖中是否存在著乙個從源點s 可達的負權迴路。若不存在這樣的...

Bellman ford 演算法詳解

昨天說的dijkstra固然很好用,但是卻解決不了負權邊,想要解決這個問題,就要用到bellman ford.我個人認為bellman ford比dijkstra要好理解一些,還是先上資料 有向圖 5 712 8135 23 6 5 4 324 735 2 45 3 在講述開,先設幾個陣列 orig...