Bellman-Ford algorithm (tsz. Bellman-Ford algorithms)
A Bellman–Ford algoritmus egy gráfbejáró eljárás, amely egy adott kezdőcsúcstól (forrástól) minden más csúcsig a legrövidebb út hosszát számítja ki súlyozott, irányított gráfokban, akár negatív élsúlyokkal is. Emellett képes kimutatni, ha negatív súlyú kör (cycle) létezik, amelyre a legrövidebb út nem definiált (végtelenül csökkenthető).
2. Az algoritmus ötlete
Inicializálás
parent
mutató a visszakövethető úthoz (opcionális).Relaxeálás (élcsökkentés) – Minden élen a súlyával megpróbáljuk csökkenteni a rá vonatkozó távolságbecslést:
– Ez a művelet biztosítja, hogy iterációról iterációra egyre pontosabb becsléseink legyenek.
Iterációk száma – Egy gráf legrövidebb útjai legfeljebb élből állnak, ahol a csúcsok száma. – Így teljes “relaxeálási kört” futtatunk végig az összes élen, ami garantálja, hogy minden csúcs távolsága konvergáljon a valódi legkisebb értékre.
Negatív kör detektálás – Végül még egyetlen plusz relaxációs körön menünk át az éleken. – Ha ilyenkor bármely él tovább tud csökkenteni egy csúcs távolságát, akkor negatív kör létezik, mert ekkor a legrövidebb út hosszát végtelenül csökkenteni lehet.
3. Pseudokód
BellmanFord(G, w, s): // G = (V, E) irányított gráf, w: E→ℝ súlyfüggvény, s: forráscsúcs for minden v ∈ V: dist = ∞ parent = NIL dist = 0 // |V|-1 relaxációs kör for i = 1 to |V|-1: for minden (u, v) ∈ E: if dist + w(u, v) < dist: dist = dist + w(u, v) parent = u // Negatív kör ellenőrzés for minden (u, v) ∈ E: if dist + w(u, v) < dist: return "Negatív kör található" return dist, parent
4. Idő- és helykomplexitás
dist
és egy parent
tömböt ⇒ .
5. Példa lépésről lépésre Legyen az alábbi gráf, élsúlyokkal:
(5) A ——→ B | \ (2)| \(2) ↓ C D ←—— E (−4)
Élek:
Forrás: .
Kezdeti állapot
dist=0, dist=∞, dist=∞, dist=∞, dist=∞
1. relaxációs kör
2. kör
3. kör (|V|=5 ⇒ 4 relaxációs körig megyünk, de láthatóan gyorsan konvergált)
– További körökben nem történik változás, így a konvergencia már korábban bekövetkezett.
Negatív kör ellenőrzés – Semelyik él esetében nem csökkenthető tovább az érték ⇒ nincs negatív kör.
Végül:
dist = {A:0, B:5, C:7, D:2, E:10} parent = {A:NIL, B:A, C:B, D:A, E:C}
6. Python-példa
def bellman_ford(graph, source):
"""
graph: lista az élekről, minden él (u, v, w)
source: forráscsúcs
Visszatér: (dist, parent) vagy hibajelzés negatív kör esetén
"""
# Csúcsok kigyűjtése
vertices = set()
for u, v, w in graph:
vertices.add(u); vertices.add(v)
dist = {v: float('inf') for v in vertices}
parent = {v: None for v in vertices}
dist = 0
# |V|-1 relaxáció
for _ in range(len(vertices) - 1):
updated = False
for u, v, w in graph:
if dist + w < dist:
dist = dist + w
parent = u
updated = True
if not updated:
break # ha nem változott semmi, már konvergált
# Negatív kör ellenőrzés
for u, v, w in graph:
if dist + w < dist:
raise ValueError("Negatív súlyú kör található")
return dist, parent
# Példa használat
edges = [
('A','B',5), ('A','D',2), ('B','C',2),
('C','E',3), ('E','D',-4)
]
distances, parents = bellman_ford(edges, 'A')
print("Távolságok:", distances)
print("Szülők:", parents)
7. Alkalmazások és összehasonlítás
8. Összefoglalás A Bellman–Ford algoritmus robusztus eszköz súlyozott gráfok legrövidebb útjainak kiszámítására, különösen negatív élsúlyok esetén, és egyszerű módon detektálja a negatív köröket. Bár időkomplexitása miatt nagy gráfokban lassabb lehet, előnye a szélesebb alkalmazhatóság és a negatív kör érzékelése.