THEMA: K urzeste Пege in raphen: Die Algorithmen von Dijkstra

Werbung
Vorlesung Informatik B, 10. 07. 2006
THEMA: Ku
 rzeste Wege in Graphen: Die Algorithmen von Dijkstra und Floyd{
Warshall; Transitive Hu
 lle
Bestimmung ku
 rzester Wege in Graphen
Sei G = (V; E ) ein gerichteter Graph mit einer Gewichtsfunktion w, die den Kanten nichtnegative
Gewichte (`Lange' der Kante) zuordnet.
Wir denieren das Gewicht eines Weges als die Summe der Gewichte seiner Kanten. Ziel ist es fur
einen Startknoten s leichteste (`kurzeste') Wege zu allen anderen erreichbaren Knoten zu berechnen.
Voru
 berlegungen:
Die Eigenschaft `kurzester Weg' vererbt sich auf Teilwege. Ist also p ein kurzester Weg von
u nach v u ber die Zwischenknoten u0 und v0 , dann ist der induzierte Teilweg von u0 nach v0
auch ein kurzester.
Damit kann man kurzeste Wege von s zu allen erreichbaren Knoten so auswahlen, dass sie
einen Baum bilden, den man kompakt mittels der {Zeiger verwaltet.
Breitensuche ist ein Spezialfall eines Kurzesten-Wege-Problems, alle Kanten haben Gewicht
1.
Der Algorithmus von Dijkstra
Idee des Algorithmus
In Analogie zum MST{Algorithmus von Prim vergroern wir in jedem Schritt eine Menge
S von Knoten, fur die die Abstande von s und kurzeste Wege bereits bestimmt sind. Der
Algorithmus ist `greedy'.
Fur jeden Knoten v in V n S halten wir einen Schlussel d[v] aufrecht, der sagt, wie lang der
bisher bekannte kurzeste Weg von s nach v ist und wir merken uns auch, wer der Vorganger
[v] auf einem solchen Weg ist. Die Schlussel d[v] werden in einer Prioritats{Warteschlange
verwaltet.
Wir nehmen den Kopf u der Warteschlange in S auf und mussen uberprufen, ob man dessen
Nachbarn v von s aus uber u besser (d.h. auf kurzerem Weg als bisher bekannt) erreichen
kann. Dies nennt man Relaxieren und formal ist es folgendes:
Falls d[v] > d[u] + w(u; v) dann ersetze d[v] durch d[u] + w(u; v) und [v] zeigt jetzt auf u.
u
v
Adj[u]
s
Für Knoten in S sind kürzeste
wege schon gefunden (dick)
Knoten u hat kleinsten Schlüssel
in V\S. .Er wird in S aufgenommen und
seine Nachbarn überprüft (relaxieren)
Hier ist der formale Pseudocode.
(G; w; s)
01 for jede Ecke v 2 V(G)
02
do d[v]
1
Dijkstra
03
[v]
04 d[s]
0
05 S
06 Q
;
Nil
V(G)
07 while Q
6= ;
08
do u
09
S
10
for jede Ecke v
11
Extract-Min(Q)
S
[ fug
do if d[v]
12
2 Adj[u]
> d[u] + w(u,v)
then d[v]
d[u] + w(u,v)
[v] = u
13
Was ist die Komplexitat dieses Algorithmus? Dies hangt von der konkreten Realisierung der Prioritatsschlange ab:
Verwendet man unsortierte Arrays, so kostet Extract-Min im worst case Lange des Arrays, wahrend
die Update-Operation in konstanter Zeit geht, also insgesamt O(jV j ).
2
Verwendet man binare Heaps, so kostet Extract-Min O(log jV j) und jeder Update O(log jV j), insgesamt O(jE j log jV j).
Korrektheitsbeweis fu
 r den Algorithmus:
Bezeichne d (s; v) die Lange eines kurzesten Weges von s nach v. Wir mussen zeigen, dass in
dem Moment, wenn v in S aufgenommen wird, d (s; v) = d[v] gilt (danach wird d[v] ja nicht mehr
verandert!)
Zunachst ist klar, dass im Algorithmus zu jedem Zeitpunkt und fur jeden Knoten v gilt d[v] d (s; v).
G
G
G
Indirekter Beweis:
u
S
s
x
y
Ein kürzester Weg von s nach u, y der erste Knoten
außerhalb von S, x sein Vorgänger in S
1. Sei u der zeitlich erste (!!) Knoten, fur den bei Aufnahme in S gilt d[u] > d (s; u), also der
Algorithmus einen Fehler macht.
2. Sei y erster Knoten auf einem tatsachlich kurzestem Weg von s nach u, der in V n S liegt. Fur
y gilt aber d[y] = d (s; y).
Weil: d[x] ist korrekt fur Vorganger x 2 S von y. Nach Annahme war u ja erster Fehler. Bei
Aufnahme von x in S wurde Kante (x; y) relaxiert, also ist auch d[y] korrekt. Wenn y = u,
sind wir hier schon fertig.
3. Ansonsten haben wir:
d[u] > d (s; u) = d (s; y) + d (y; u) = d[y] + d (y; u):
Aber damit ist d[u] > d[y] bei der Aufnahme von u in S , weil d (y; u) nichtnegativ ist.
4. Das ist aber der gesuchte Widerspruch, der Algorithmus hat u genommen, hatte aber tatsachlich
y mit dem kleineren Schlussel nehmen mussen.
G
G
G
G
G
G
G
Der Algorithmus von Floyd-Warshall
Ziel ist es, fur einen gerichteten Graphen G = (V; E ) und eine Kantengewichtsfunktion w alle
Abstande zwischen Knoten und realisierende kurzeste Wege zu nden. Das heit dann All-PairShortest-Path-Problem.
Wir setzen wieder voraus, dass es keine Kreise mit negativem Gesamtgewicht gibt.
Naturlich lat sich dieses Problem durch Anwendung des Dijkstra-Algorithmus fur jeden moglichen
Startknoten s losen.
Wir werden aber sehen, dass es konzeptionell viel einfacher geht und insbesondere nur elementare
Datenstrukturen notig sind.
Das dahinter stehende algorithmische Prinzip ist das des sogenannten Dynamischen Programmierens.
Die Idee: Wir benennen die Knoten mit 1; ::::; n. Ziel ist, eine n n{Matrix D zu berechnen,
deren Eintrage d die Lange eines kurzesten gerichteten Weges von i nach j angibt.
Zusatzlich werden wir mit -Verweisen wie bei Dijkstra tatsachlich kurzeste Wege implizit verwalten. Sei also die n n{Matrix, deren Eintrag der Vorganger des Knotens j auf einem kurzesten
i;j
i;j
Weg von i nach j ist.
Wir werden zunachst starke Einschrankungen auf das Problem legen, die eingeschrankten Problem
losen und dann die Einschrankungen wieder Schritt fur Schritt wegnehmen, bis wir wieder beim
Ausgangsproblem sind.
Wie sehen die Einschrankungen aus? Wir betrachten fur die Knoten i; j nicht mehr alle Wege
von i nach j und suchen darunter einen kurzesten, sondern wir schranken die Menge der moglichen
Zwischenknoten (die diese Wege benutzen konnen, aber nicht mussen) ein.
Wir denieren: Sei d die Lange eines kurzesten Weges von i nach j , der nur Zwischenknoten
aus der Knotenmenge f1; :::; kg benutzt. Nichtdenierte Werte werden auf 1 gesetzt. Fur k = 0
erlauben wir gar keine Zwischenknoten!
(k )
i;j
Die sind analog deniert, NIL falls der Knoten nicht existiert.
(k )
i;j
Was hilft uns dies?
Die Matrizen D der d {Werte und die Matrizen der Knoten lassen sich bottom{up sehr einfach berechnen.
Initialisierung: Die Matrizen D und kann man direkt aus der Adjazenzmatrix A = (a )
des Graphen (dies ist hier die geeignete Datenstruktur, a die Lange der Kante) ablesen.
i;j
(0)
i;j
k)
gewinnt man aus D
(k
1)
i;j
8
<0
=: a
1
8
<i
=: i
NIL
i;j
i;j
i=j
9i ! j
sonst
i=j
9i ! j
sonst
mittels der folgenden rekursiven Beziehung:
= minfd ; d
+d g
Denn wenn der Knoten k als Zwischenknoten vorkommt dann nur ein Mal!!
Und analog:
d(
k)
(k
i;j
(
k)
i;j
=
(
k
i;j
k
1)
1)
k;j
falls d
sonst
Es ist oensichtlich D = D und = .
(n)
1)
i;j
(
(
(n)
(k )
i;j
(0)
d(0)
D(
(k )
i;j
(0)
(k )
(k )
Zentrale Beobachtung:
(k
1)
(k
i;k
(k
i;j
1)
1)
k;j
< d(
k
i;k
1)
+d
(k
k;j
1)
Alle Zwischenknoten stammen aus der Knotenmenge {1,....,k}
i
j
k
Nur Zwischenknoten aus der Knotenmenge
{1,.......,k−1}
Π (k)
i,j
Nur Zwischenknoten aus der Knotenmenge
{1,.......,k−1}
(k−1)
Π (k)
= Π
i,j
i,j
Alle Zwischenknoten aus {1,....,k}, ABER der Knoten k tritt nicht auf!
j
i
Dies ergibt sofort den folgenden Algorithmus fur die Bestimmung von D :
(n)
(W ) (Ecken 1,2,...,n; W ist n n{Matrix der Kantengewichte,
1 falls (i,j) keine Kante ist und =Kantengewicht sonst)
Floyd{Warshall
0 f
ur i=j , =
01 n
rows[W]
02 D(0)
03 for k
04
d.h. wi;j =
W
1 to n
do for i
05
1 to n
do for j
1 to n
(k )
06
(n)
di;j
(k
min( di;j
1)
(k
, di;k
1)
(k
+ dk;j
1)
)
07 return D
Dieser Algorithmus hat eine Komplexitat von O(n ).
3
: Die transitive Hulle eines gerichteten Graphen G = (V; E ) ist der Graph G =
(V; E ), wobei es in G eine Kante von i nach j gibt, falls in G ein gerichteter Weg von i nach j
existiert.
Eine Variante
Man kann eine einfache Abwandlung des Floyd{Warshall dazu benutzen, die transitive Hulle zu
bestimmen.
Dazu sei t eine Boolesche Variable, die 1 ist, falls ein gerichteter Weg mit Zwischenknoten aus
f1; :::; kg von i nach j existiert und 0 sonst.
Oensichtlich gilt:
t =t
_ (t ^ t )
mit der Initialisierung
8 1 i=j
<
t = 1 9i ! j
: 0 sonst
(k )
i;j
(k )
(k
i;j
i;j
(0)
i;j
1)
(k
i;k
1)
(k
k;j
1)
Herunterladen