ベルマンフォードアルゴリズム
ベルマンフォードアルゴリズムは、一般に、エッジの重みが負になる可能性がある単一ソースの最短経路問題を解決します。重み付き有向グラフが与えられた場合G =(V、E)G =(V、E)G=(V 、E )および重み関数w:E − R w:ERw:E−R、ベルマンフォードアルゴリズムはブール値を返し、ソースノードから到達できる負の重みを持つループがあるかどうかを示します。そのようなループがある場合、アルゴリズムは解決策がないことを通知します。そのようなループはありませんループが存在し、アルゴリズムは最短パスとその重みを与えます。
ベルマンフォードアルゴリズムの実装手順:
-
ステップ1:重み付きのグラフから始めます
-
ステップ2:開始ノードを選択し、残りのノードのパス距離を無限大に割り当てます
-
ステップ3:各エッジにアクセスし、緩和操作を実行して、ノード距離を更新します
-
ステップ4:VVを操作する必要があるVの時間は、最悪の場合、ノードの経路距離は、V時間を調整する必要があるかもしれないので
- ステップ5:上記のプロセスを繰り返し、最後に開始ノードから各ノードまでのパス距離を調整および更新して、最終結果を取得し
ます。ベルマンフォードアルゴリズムの複雑さはO(VE)O(VE)です。O (V E )
Pythonは次のように実装されています。
# -*-coding:utf8-*-
import sys
class Graph:
def __init__(self, V):
self.V = V
self.graph = []
# add edges
def add_edge(self, s, d, w):
self.graph.append([s, d, w])
# print the solution
def print_solution(self, dist):
print(" Vertex Distance from Source")
for i in range(self.V):
print("{0}\t\t{1}".format(i, dist[i]))
def bellman_ford(self, src):
# step 1: fill the distance array and predecessor array
dist = [float("Inf")] * self.V
# Mark the source vertex
dist[src] = 0
# step 2 : relax edges |V|-1 times
for _ in range(self.V - 1):
for s, d, w in self.graph:
if dist[s]!= float("Inf") and dist[s] + w < dist[d]:
dist[d] = dist[s] + w
# step 3: detect negative cycle
for s, d, w in self.graph:
if dist[s] != float("Inf") and dist[s] + w < dist[d]:
print("Graph contains negative weight cycle")
return
# No negative weight cycle found, print the distance
self.print_solution(dist)
if __name__=='__main__':
g = Graph(5)
for s,d,w in [(0,1,4),(0,2,2),(1,2,3),(2,1,1),(1,3,2),(1,4,3),(2,4,5),(2,3,4),(4,3,-5)]:
g.add_edge(s,d,w)
g.bellman_ford(0)
ダイクストラアルゴリズム
ダイクストラアルゴリズムは、重み付きの有向グラフ上の単一ソース最短経路問題を解決します。アルゴリズムでは、すべてのエッジの重みが負でない必要があります。最小スパニングツリーとの違いに注意してください。最小スパニングツリーにはグラフ内のすべてのノードが含まれている必要がありますが、ダイクストラアルゴリズムは任意の2つのノード間の最短パスを見つけることです。
ダイクストラのアルゴリズムの実装手順は次のとおりです。
-
ステップ1:重み付きのグラフから始めます
-
ステップ2:開始ノードを選択し、他のノードのパスを無限大に設定します
-
ステップ3:各ノードをトラバースし、パスの長さを更新します
-
ステップ4:ノードのパス長が新しいパス長より短い場合、ノードは更新されません
-
ステップ5:トラバースされたノードはパスの長さを更新しなくなりました
-
ステップ6:各反復で、トラバースされていないノードを選択し、パスが最小のノードを選択します。これにより、次の図のノード5がノード7の前に選択されます。
-
ステップ7:すべてのノードが
ダイクストラアルゴリズムを通過するまで上記のステップを繰り返します。時間計算量はO(E log V)O(ElogV)です。O (E l o g V )
pythonは次のように実装されます。
# -*-coding:utf8 -*-
import sys
class Graph:
def __init__(self, vertices, edgs):
self.vertices= vertices
self.edgs = edgs
self.num_of_vertices = len(vertices[0])
self.visited_and_distance = [[0,0]]
def to_be_visited(self):
v = -1
for index in range(self.num_of_vertices):
if self.visited_and_distance[index][0] == 0 and (v < 0 or self.visited_and_distance[index][1] <= self.visited_and_distance[v][1]):
v = index
return v
def distance(self):
for i in range(self.num_of_vertices-1):
self.visited_and_distance.append([0, sys.maxsize])
for vertex in range(self.num_of_vertices):
# find next vertex to be visited
to_visit = self.to_be_visited()
for neighbor_index in range(self.num_of_vertices):
if self.vertices[to_visit][neighbor_index] ==1 and self.visited_and_distance[neighbor_index][0] == 0:
new_distance = self.visited_and_distance[to_visit][1] + edges[to_visit][neighbor_index]
if self.visited_and_distance[neighbor_index][1] > new_distance:
self.visited_and_distance[neighbor_index][1] = new_distance
self.visited_and_distance[to_visit][0] = 1
if __name__=='__main__':
vertices = [[0, 0, 1, 1, 0, 0, 0],
[0, 0, 1, 0, 0, 1, 0],
[1, 1, 0, 1, 1, 0, 0],
[1, 0, 1, 0, 0, 0, 1],
[0, 0, 1, 0, 0, 1, 0],
[0, 1, 0, 0, 1, 0, 1],
[0, 0, 0, 1, 0, 1, 0]]
edges = [[0, 0, 1, 2, 0, 0, 0],
[0, 0, 2, 0, 0, 3, 0],
[1, 2, 0, 1, 3, 0, 0],
[2, 0, 1, 0, 0, 0, 1],
[0, 0, 3, 0, 0, 2, 0],
[0, 3, 0, 0, 2, 0, 1],
[0, 0, 0, 1, 0, 1, 0]]
graph = Graph(vertices, edges)
graph.distance()
i = 0
for distance in graph.visited_and_distance:
print("Distance of ", chr(ord('a')+i), "from source vertex: ", distance[1])
i+=1