Algorithm - Graph Theory - Lec 2

Single Source Shortest Path - Bellman-Ford Algorithm

圖的一個常見應用場合是想找出某兩點之間的最短(/長)路徑,此時的邊權重又視為兩節點之間的距離。

Shortest Path Problem

Given a graph $G$, a starting vertex $s$ and edge cost $c_e$
Want: Find the path with min. total cost from $s \rightarrow v$ for some $v$

Bellman-Ford Algorithm

優點:

  • 可以處理有負邊的圖
  • 能偵測負環 ( Negative Cycle )

Relax (鬆弛)

最短路徑演算法中常看到的名詞,先看程式碼

def relax(u,v):
  if d[v] > d[u] + w(u,v):
    d[v] = d[u] + w(u,v) # 當前最短路的 cost
    π[v] = u # back-tracking

簡單來說就是如果遇到 cost 更小的路徑,就更新。
這也建構於最短路徑問題的特性,若從 $s$$v$ 的最短路徑中經過 $u$ ,那麼可以確定子路徑 $s \rightarrow u$ 亦為其兩點間的最短路。

Psuedo Code

# Init
for v in G(V):
  d[v] = ∞ 
  π[v] = NULL
d[s] = 0

# Iterate |V| - 1 times
for i in range(|V| - 1):
  for e(u,v) in E:
    relax(u,v)

複雜度為 $\mathcal{O}(VE)$

一些觀察

  • 實際上也不用跑到 $|V| - 1$ 次才停止,在某一回合如果沒有更新,那麼往後的回合也不可能更新了,此時便可以停止。

  • 遍歷邊的順序,影響了需要幾回合才能找到最短路,那麼最佳的順序是什麼呢? ($\rightarrow$ see Dijkstra)

Correctness

  • 假設圖上沒有負環,the shortest path from $s \rightarrow v$ has $\leq |V|-1$ edges

proof : By contradiction,若用了 $\geq |V|$ 條邊,該路徑必存在 cycle (某些點被重複拜訪),但負邊不存在,這麼做只是徒增 cost ( 故可把 cycle 拔掉 ),得證。

  • $|V| - 1$ 個回合必可找到最短路,考慮 $s \rightarrow v $ 的最短路徑,
\[ s \stackrel{c_1}{\longrightarrow} v_1 \stackrel{c_2}{\longrightarrow} v_2 \stackrel{c_3}{\longrightarrow} \cdots v_{k-1} \stackrel{c_k}{\longrightarrow} v \]

After relax( s , $v_1$ ) in round 1,d[$v_1$] = $c_1$

          relax($v_1$, $v_2$ ) in round 2,d[$v_2$] = $c_1 + c_2$
          $\cdot$
          $\cdot$
          $\cdot$

          relax($v_{k-1}$, $v$) in round $k$,d[$v$] = $c_1 + c_2 + \cdots + c_k$

可知在 $k$ 回合內必可完成更新,又 $k \leq |V| - 1$

由上方這個 Claim ,如果 d[$v$] 在 $|V|$ round 有所改動的話,代表了負環存在

Implementation

做兩次 Bellman-Ford ,偵測出所有負環。
第二次 Bellman-Ford 中,邏輯判斷將d[$v$] 設成 $- \infty$ 的情況共有兩個

  • $- \infty$ 的傳染性:
if(dist[e.edge.first] == INT_MIN)
        dist[e.edge.second] = INT_MIN;
  • negative cycle 存在於 $s \rightarrow v$ 的最短路中,則將 d[$v$] 設成 $- \infty$
if(dist[e.edge.first] != INT_MAX && dist[e.edge.first] + e.weight < dist[e.edge.second])
        dist[e.edge.second] = INT_MIN;

為什麼還需要再跑 $|V| - 1$ 次?
是因為要將 $- \infty$ 傳染遍整個環,需要負環長度個回合,而最大的負環長度 $\leq |V| - 1$

 View    times
 
comments powered by Disqus