標籤:
1 # Bellman-Ford核心演算法 2 # 對於一個包含n個頂點,m條邊的圖, 計算源點到任意點的最短距離 3 # 迴圈n-1輪,每輪對m條邊進行一次鬆弛操作 4 5 # 定理: 6 # 在一個含有n個頂點的圖中,任意兩點之間的最短路徑最多包含n-1條邊 7 # 最短路徑肯定是一個不包含迴路的簡單路徑(迴路包括正權迴路與負權迴路) 8 # 1. 如果最短路徑中包含正權迴路,則去掉這個迴路,一定可以得到更短的路徑 9 # 2. 如果最短路徑中包含負權迴路,則每多走一次這個迴路,路徑更短,則不存在最短路徑10 # 因此最短路徑肯定是一個不包含迴路的簡單路徑,即最多包含n-1條邊,所以進行n-1次鬆弛即可11 12 13 G = {1:{1:0, 2:-3, 5:5},14 2:{2:0, 3:2},15 3:{3:0, 4:3},16 4:{4:0, 5:2},17 5:{5:0}}18 19 20 21 def getEdges(G):22 """ 輸入圖G,返回其邊與端點的列表 """23 v1 = [] # 出發點 24 v2 = [] # 對應的相鄰到達點25 w = [] # 頂點v1到頂點v2的邊的權值26 for i in G:27 for j in G[i]:28 if G[i][j] != 0:29 w.append(G[i][j])30 v1.append(i)31 v2.append(j)32 return v1,v2,w33 34 class CycleError(Exception):35 pass36 37 def Bellman_Ford(G, v0, INF=999):38 v1,v2,w = getEdges(G)39 40 # 初始化源點與所有點之間的最短距離41 dis = dict((k,INF) for k in G.keys())42 dis[v0] = 043 44 # 核心演算法45 for k in range(len(G)-1): # 迴圈 n-1輪46 check = 0 # 用於標記本輪鬆弛中dis是否發生更新47 for i in range(len(w)): # 對每條邊進行一次鬆弛操作48 if dis[v1[i]] + w[i] < dis[v2[i]]:49 dis[v2[i]] = dis[v1[i]] + w[i]50 check = 151 if check == 0: break52 53 # 檢測負權迴路54 # 如果在 n-1 次鬆弛之後,最短路徑依然發生變化,則該圖必然存在負權迴路55 flag = 056 for i in range(len(w)): # 對每條邊再嘗試進行一次鬆弛操作57 if dis[v1[i]] + w[i] < dis[v2[i]]: 58 flag = 159 break60 if flag == 1:61 # raise CycleError()62 return False63 return dis64 65 v0 = 166 dis = Bellman_Ford(G, v0)67 print dis.values()
python資料結構與演算法——圖的最短路徑(Bellman-Ford演算法)解決負權邊