Hi,
gleicher Beitrag wie im Chit-Chat:
Dijkstra kommt nicht mit negativen Kantengewichten zurecht. Ein Beispiel, an dem Dijkstra fehlschlagen soll, ist zum Beispiel folgender Graph (V, E) mit Kostenfunktion c und Startknoten 1:
Der kuerzeste Weg von 1 zu 2 ist also der Pfad ((1, 3), (3, 2)) mit Gewicht 0.
Mit einer Prioritaetsliste Q und Startknoten s habe ich folgende Referenz-Implementierung von Dijkstra fuer einen Graphen G = (V, E):
Inwiefern schlaegt der Algorithmus fuer das Beispiel fehl? Ich sehe das so:
Knoten s = 1 wird in Q eingefuegt. Ausgehende Kanten sind (1, 2) und (1, 3), beide werden in der foreach Schleife entdeckt und relaxiert. Dabei werden die Knoten 2 und 3 in Q eingefuegt, ausserdem wird d[2] = 1 und d[3] = -2 gesetzt. Da c(1, 2) < c(1, 3) wird im naechsten Durchlauf der while Schleife also Knoten 2 untersucht; es gibt keine ausgehende Kanten, und damit wird die foreach Schleife ueberhaupt nicht ausgefuehrt. Also wird Knoten 3 zuletzt betrachtet. Jetzt entdeckt die foreach Schleife aber die Kante (3, 2) und relaxiert, da d[3] + c(3, 2) = 2 - 2 = 0 < 1 = d[2] wird d[2] = 0 gesetzt und Knoten 2 wird erneut in Q eingefuehrt (es passiert aber dann nichts mehr). Also liefert der Algorithmus zuletzt das Ergebnis
und das ist korrekt.
Die Implementierung stammt aus einem Buch ueber Algorithmen, das Beispiel (oder ein aehnliches) gibt es auf zahlreichen Internetseiten. Lese ich den Algorithmus irgendwo falsch? Findet jemand ein Beispiel mit negativen Kanten (aber ohne negativen Zyklen), bei dem der Algorithmus versagt?
gleicher Beitrag wie im Chit-Chat:
Dijkstra kommt nicht mit negativen Kantengewichten zurecht. Ein Beispiel, an dem Dijkstra fehlschlagen soll, ist zum Beispiel folgender Graph (V, E) mit Kostenfunktion c und Startknoten 1:
Code:
V = (1, 2, 3) E = ((1, 2), (1, 3), (3, 2)), c(1, 2) = 1, c(1, 3) = 2, c(3, 2) = -2
Mit einer Prioritaetsliste Q und Startknoten s habe ich folgende Referenz-Implementierung von Dijkstra fuer einen Graphen G = (V, E):
Code:
Function Dijkstra(s: NodeId)
d = <infty, ..., infty>
parent = <null, ..., null>
d[s] := 0
parent[s] := s
Q.insert(s)
while Q != empty do
u := Q.deleteMin
foreach e = (u, v) in E do
if d[u] + c(e) < d[v] then
d[v] := d[u] + c(e)
parent[v] := u
if v in Q then Q.decreaseKey(v)
else Q.insert(v)
return (d, parent)
Knoten s = 1 wird in Q eingefuegt. Ausgehende Kanten sind (1, 2) und (1, 3), beide werden in der foreach Schleife entdeckt und relaxiert. Dabei werden die Knoten 2 und 3 in Q eingefuegt, ausserdem wird d[2] = 1 und d[3] = -2 gesetzt. Da c(1, 2) < c(1, 3) wird im naechsten Durchlauf der while Schleife also Knoten 2 untersucht; es gibt keine ausgehende Kanten, und damit wird die foreach Schleife ueberhaupt nicht ausgefuehrt. Also wird Knoten 3 zuletzt betrachtet. Jetzt entdeckt die foreach Schleife aber die Kante (3, 2) und relaxiert, da d[3] + c(3, 2) = 2 - 2 = 0 < 1 = d[2] wird d[2] = 0 gesetzt und Knoten 2 wird erneut in Q eingefuehrt (es passiert aber dann nichts mehr). Also liefert der Algorithmus zuletzt das Ergebnis
Code:
d[1] = 0, d[2] = 0, d[3] = 2,
Die Implementierung stammt aus einem Buch ueber Algorithmen, das Beispiel (oder ein aehnliches) gibt es auf zahlreichen Internetseiten. Lese ich den Algorithmus irgendwo falsch? Findet jemand ein Beispiel mit negativen Kanten (aber ohne negativen Zyklen), bei dem der Algorithmus versagt?