python數據結構與算法——圖的最短路徑(Bellman-Ford算法)解決負權邊


 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,w
33 
34 class CycleError(Exception):
35     pass
36 
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] = 0
43 
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 = 1
51         if check == 0: break
52     
53     # 檢測負權回路
54     # 如果在 n-1 次松弛之后,最短路徑依然發生變化,則該圖必然存在負權回路
55     flag = 0
56     for i in range(len(w)):             # 對每條邊再嘗試進行一次松弛操作
57         if dis[v1[i]] + w[i] < dis[v2[i]]: 
58             flag = 1
59             break
60     if flag == 1:
61 #         raise CycleError()
62         return False
63     return dis
64 
65 v0 = 1
66 dis = Bellman_Ford(G, v0)
67 print dis.values()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM