Effiziente Algorithmen - Graphdurchläufe

Werbung
Starke Zusammenhangskomponenten
Einleitung
2.4 Starke Zusammenhangskomponenten in Digraphen
Definition 2.4.1
Zwei Knoten v und w in einem Digraphen G heißen äquivalent, wenn
v ! w und w ! v gilt. Notation: v " w .
Es gilt:
(a) Die so definierte Relation ist reflexiv, transitiv, und symmetrisch, also
eine Äquivalenzrelation.
(b) Zwei Knoten v und w sind äquivalent genau dann wenn sie identisch
sind oder es in G einen (gerichteten) Kreis gibt, auf dem beide Knoten
liegen.
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
51
Starke Zusammenhangskomponenten
Einleitung
Definition 2.4.2
Die Äquivalenzklassen zur Relation " heißen starke
Zusammenhangskomponenten von G .
Beispiel: 5 starke Zusammenhangskomponenten
5
4
9
8
12
1
6
7
11
14
FG KTuEA, TU Ilmenau
2
3
10
13
Effiziente Algorithmen – Sommersemester 2012
52
Starke Zusammenhangskomponenten
Einleitung
Definition 2.4.2
Die Äquivalenzklassen zur Relation " heißen starke
Zusammenhangskomponenten von G .
Beispiel: 5 starke Zusammenhangskomponenten, 2 DFS-Bäume.
5
4
9
8
12
1
6
7
11
14
FG KTuEA, TU Ilmenau
2
3
10
13
Effiziente Algorithmen – Sommersemester 2012
52
Starke Zusammenhangskomponenten
Einleitung
Lemma 2.4.3
Sei C ⊆ V eine starke Zusammenhangskomponente (s.Z.K.). Dann gilt:
Wenn DFS(G ) ausgeführt wird, dann liegen die Knoten von C alle in
einem Tiefensuchbaum.
M.a.W.: Jeder Tiefensuchbaum ist selbst starke Z.K. oder lässt sich
(disjunkt) in mehrere starke Z.K.n zerlegen.
Beweis: Es sei vC der erste Knoten v ∈ C , für den dfs(v ) aufgerufen wird.
Sei v ∈ C beliebig. Dann ist v von vC aus auf einem Weg in G erreichbar.
Behauptung: Wenn vC = v0 , v1 , . . . , vt = v ein solcher Weg ist, dann
liegen alle Knoten vi des Weges sogar in C.
(Beweis hierfür: Weil C s.Z.K. ist, gilt auch v ! vC . Zusammen mit
vC ! vi und vi ! v ergibt sich vi " vC , also vi ∈ C .)
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
53
Starke Zusammenhangskomponenten
Einleitung
Zu dem Zeitpunkt, zu dem dfs(vC ) aufgerufen wird, sind die Knoten
v0 , v1 , . . . , vt = v alle noch neu (nach Wahl von v0 = vC ).
⇒ (nach Satz 2.1.3, dem Satz vom weißen Weg“)
”
v wird Nachfahr von vC im Tiefensuchbaum.
#
NB: Es folgt: vC hat in C (die kleinste dfs-Nummer und)
die größte f-Nummer.
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
54
Starke Zusammenhangskomponenten
Einleitung
Um mit Tiefensuche die starken Zusammenhangskomponenten zu finden,
muss man verhindern, dass in einem Baum mehrere solche Komponenten
sitzen (wie im Bild oben).
Trick 1: Führe DFS im Umkehrgraphen“ G R durch, der durch Umkehren
”
aller Kanten in G entsteht.
5
4
9
2
3
8
12
14
6
7
11
1
10
13
G im Original.
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
55
Starke Zusammenhangskomponenten
Einleitung
Um mit Tiefensuche die starken Zusammenhangskomponenten zu finden,
muss man verhindern, dass in einem Baum mehrere solche Komponenten
sitzen (wie im Bild oben).
Trick 1: Führe DFS im Umkehrgraphen“ G R durch, der durch Umkehren
”
aller Kanten in G entsteht.
5
4
9
2
3
8
12
14
6
7
11
1
10
13
Umkehrung G R von G .
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
55
Starke Zusammenhangskomponenten
Einleitung
Beobachtung: G R hat dieselben starken Zusammenhangskomponenten
wie G .
(Die Kreise in den beiden Graphen sind dieselben, nur mit umgekehrter
Durchlaufreihenfolge.)
5
4
9
8
12
1
6
7
11
14
FG KTuEA, TU Ilmenau
2
3
10
13
Effiziente Algorithmen – Sommersemester 2012
56
Starke Zusammenhangskomponenten
Einleitung
Trick 2: Verwende f-Nummern der ersten DFS, um die Reihenfolge der
Knoten in der Hauptschleife der zweiten DFS (in G R ) zu bestimmen.
6
7
14
5
4
3
4
5
2
1
3
8
9
12
8
12
10
13
11
14
6
7
11
13
10
1
2
9
Graph G mit starken Zsh.-Komponenten, Tiefensuchwald und f-Nummern
aus dem ersten DFS-Aufruf.
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
57
Starke Zusammenhangskomponenten
6
7
14
5
4
3
Einleitung
4
5
2
1
3
8
9
12
8
12
10
13
11
14
6
7
11
13
10
1
2
9
Graph G R mit starken Zsh.-Komponenten und f-Nummern für G .
Führe DFS in G R durch, untersuche dabei Knoten gemäß fallenden
f-Nummern auf Eigenschaft neu“.
”
Im Beispiel: Von 3 (14) aus wird eine s.Z.K. erreicht, von 13 (9) aus die
nächste, von (1) (5) aus die nächste, von (2) (4) aus die nächste, von 7
(3) aus die letzte. Keine s.Z.K. wird versehentlich“ betreten.
”
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
58
Starke Zusammenhangskomponenten
Der Algorithmus
Algorithmus Strong Components(G ) (von S. R. Kosaraju)
Eingabe: Digraph G = (V , E )
Ausgabe: Starke Zusammenhangskomponenten von G
(1) Berechne die f-Nummern mittels DFS(G );
(2) Bilde Umkehrgraphen“ G R durch Umkehren aller Kanten in G ;
”
(3) Führe DFS(G R ) durch;
Knotenreihenfolge: f-Nummern aus (1) absteigend
(4) Ausgabe: Die Knotenmengen der Tiefensuchbäume aus (3).
Satz 2.4.4
(a) Der Algorithmus Strong Components gibt die starken
Zusammenhangskomponenten von G aus.
(b) Die Laufzeit ist O(|V | + |E |).
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
59
Starke Zusammenhangskomponenten
Korrektheitsbeweis
Beweis von Teil (b): Die DFS-Aufrufe haben lineare Laufzeit, und auch der
Umkehrgraph lässt sich in Zeit O(|V | + |E |) berechnen (siehe Übung).
Beweis von Teil (a): Nach Lemma 2.4.3 wissen wir, dass jeder DFS-Baum
der Tiefensuche in G R Vereinigung von s.Z.K.n (von G R , also von G ) ist.
Wir zeigen im Folgenden, dass jeder solche Baum nur eine s.Z.K. enthält.
Hierfür zeigen wir, dass die Tiefensuche in G R aus jeder s.Z.K. einen
Knoten als Wurzel eines DFS-Baums wählt.
Sei dazu C ⊆ V eine beliebige s.Z.K. von G .
vC ∈ C sei der Knoten mit maximaler f-Nummer in C .
(Aus Lemma 2.4.3: In der ersten Tiefensuche in G ist dies der erste Knoten von C ,
der besucht wird.)
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
60
Starke Zusammenhangskomponenten
Korrektheitsbeweis
Lemma 2.4.5
Aus vC !G v folgt f-num(v ) ≤ f-num(vC ).
Beweis: nächste Folie. – Wir folgern für G R :
Aus v !G R vC folgt f-num(v ) ≤ f-num(vC ).
In Worten: In G R ist vC von keinem Knoten v mit größerer f-Nummer als
vC aus erreichbar.
Damit folgt aus Satz 2.1.5 (Knotenmengen der DFS-Bäume) und
der besonderen Durchlaufreihenfolge (fallende f-Nummern), dass im
zweiten DFS-Durchlauf vC Wurzel eines DFS-Baums wird. Da C beliebig
war, enthält also jede starke Zusammenhangskomponente in der
G R -Tiefensuche eine Wurzel, also muss (nach Lemma 2.4.3 für G R ) jede
dieser Komponenten für sich einen Baum bilden. Damit ist Satz 2.4.4(a)
bewiesen.
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
61
Starke Zusammenhangskomponenten
Korrektheitsbeweis
Lemma 2.4.5
Aus vC !G v folgt f-num(v ) ≤ f-num(vC ).
Beweis: O. B. d. A. gilt vC %= v .
Sei vC = v0 , v1 , . . . , vt−1 , vt = v einfacher Weg in G .
!
"#
$
=: p
1. Fall: Wenn dfs(vC ) startet, sind alle Knoten auf p neu .
Nach Satz 2.1.3 ( Satz vom weißen Weg“) wird v Nachfahr von vC im
”
DFS-Baum, also ist f-num(v ) < f-num(vC ).
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
62
Starke Zusammenhangskomponenten
Korrektheitsbeweis
Lemma 2.4.5
Aus vC !G v folgt f-num(v ) ≤ f-num(vC ).
2. Fall: Wenn dfs(vC ) startet, ist ein Knoten vi , 0<i≤t, aktiv .
Dann führt ein Schluss-Stück des roten Weges von vi zu vC .
Von vC nach vi führt der erste Teil des Weges p.
Daraus: vC " vi , also vi ∈ C .
Andererseits ist f-num(vi ) > f-num(vC ), im Widerspruch zur Wahl von
vC . Der 2. Fall kann also gar nicht eintreten.
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
63
Starke Zusammenhangskomponenten
Korrektheitsbeweis
Lemma 2.4.5
Aus vC !G v folgt f-num(v ) ≤ f-num(vC ).
3. Fall: Wenn dfs(vC ) startet, ist ein Knoten vi , 0<i≤t, fertig .
Wegen des Vorgehens der dfs-Prozedur und weil Fall 2 nicht eintritt, gilt
für i ≤ j < t, zu dem Zeitpunkt, an dem dfs(vC ) startet:
Wenn vj fertig“ ist, dann ist auch vj+1 fertig“.
”
”
(Bevor dfs(vj ) endete, wurde Kante (vj , vj+1 ) betrachtet; also kann vj+1
nicht neu“ sein.)
”
Also ist v fertig“, wenn dfs(vC ) startet.
”
Daraus folgt: f-num(v ) < f-num(vC ).
#
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
64
Tiefensuche in ungerichteten Graphen
2.5 Tiefensuche in ungerichteten Graphen
Einfacher als Tiefensuche in gerichteten Graphen.
Zweck:
Zusammenhangskomponenten finden
Spannbaum für jede Zusammenhangskomponente finden
Kreisfreiheitstest
(Diese einfachen Aufgaben kann man auch mit einer Breitensuche
erledigen.)
Komplexere Erweiterungen, z. B.
Zweifach-Zusammenhangskomponenten“, erfordern DFS. (Lit.: Buch von
”
Sedgewick, Kap. 5.)
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
65
Tiefensuche in ungerichteten Graphen
1:
v:
r
w
t
w:
t
u
v
s
n:
Adjazenzlistendarstellung mit Querverweisen.
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
66
Tiefensuche in ungerichteten Graphen
Darstellung von ungerichteten Graphen:
Adjazenzlistendarstellung mit Querverweisen.
Knotenarray: nodes[1..n].
Zu Knoten v gibt es eine lineare Liste Lv mit einem Eintrag für jede Kante
(v , w ).
Von Eintrag für Kante (v , w ) führt ein Verweis auf die Gegenkante“
”
(w , v ) in der Adjazenzliste Lw (und natürlich auch umgekehrt).
Wir können an Kanten Markierungen anbringen.
Anfangs markieren wir beide Richtungen aller Kanten mit neu“. Wir
”
stellen sicher, dass nach Benutzung der Kante (v , w ) in Richtung von v
nach w die umgekehrte Richtung nicht mehr benutzt wird, indem wir
(w , v ) mit ( gesehen“) markieren.
”
Klassifizierung in T -Kanten und B-Kanten.
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
67
Tiefensuche in ungerichteten Graphen
Algorithmus udfs(v ) (∗ Tiefensuche von v aus, rekursiv ∗)
(∗ nur für v mit status[v ] = neu aufrufen ∗)
(1) dfs count++;
(2) dfs num[v ] ← dfs count;
(3) dfs-visit(v ); (∗ Aktion an v bei Erstbesuch ∗)
(4) status[v ] ← aktiv ;
(5)
für jede neue“ Kante (v , w ) (Adjazenzliste!) tue:
”
(6)
setze Gegenkante (w , v ) auf gesehen“;
”
(7)
1. Fall: status[w] = neu: T ← T ∪ {(v , w )}; udfs(w);
(8)
2. Fall: status[w] = aktiv : B ← B ∪ {(v , w )};
(9) f count++;
(10) f num[v ] ← f count;
(11) fin-visit(v ); (∗ Aktion an v bei letztem Besuch ∗)
(12) status[v ] ← fertig.
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
68
Tiefensuche in ungerichteten Graphen
Globale Tiefensuche in (ungerichtetem) Graphen G :
Algorithmus UDFS(G ) (∗ Tiefensuche in G = (V , E ) ∗)
(1) dfs count ← 0;
(2) f count ← 0;
(3) for v from 1 to n do status[v] ← neu;
(4) T ← ∅; B ← ∅;
(5) for v from 1 to n do
(6)
if status[v] = neu then
(7)
udfs(v); (∗ starte Tiefensuche von v aus ∗)
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
69
Tiefensuche in ungerichteten Graphen
13
5
6
11
2
7
4
1
12
8
9
3
10
Ungerichteter Graph.
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
70
Tiefensuche in ungerichteten Graphen
13 6| 5
4| 6
5
3| 7
6
7
5| 1
4
2| 8
12| 10
8
7| 4
8| 3
2
11
12 9| 2
1
1| 9
11| 12
9
3
10| 13
10 13| 11
Ungerichteter Graph mit Baum- und Rückwärtskanten sowie dfs- und
f-Nummern.
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
71
Tiefensuche in ungerichteten Graphen
Satz 2.5.1
udfs(v0 ) werde aufgerufen. Dann gilt:
(a) udfs(v0 ) entdeckt genau die Knoten in der
Zusammenhangskomponente von v0 .
(b) Die Kanten (v , w ), wo udfs(w ) unmittelbar aus udfs(v ) aufgerufen
wird, bilden einen (gerichteten) Baum mit Wurzel v0 .
( Tiefensuchbaum“: ein Spannbaum“)
”
”
(c) (Satz vom weißen Weg) u ist im DFS-Baum ein Nachfahr von v
genau dann wenn zum Zeitpunkt des Aufrufs udfs(v ) ein Weg von v
nach u existiert, der nur neue (weiße) Knoten enthält.
Laufzeit (mit Initialisierung): O(|V | + |Ev0 |), wo Ev0 die Menge der Kanten in der
Zusammenhangskomponente von v0 ist.
Beweis: Ähnlich zum gerichteten Fall.
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
72
Tiefensuche in ungerichteten Graphen
Satz 2.5.2
UDFS(G ) werde aufgerufen. Dann gilt:
(a) Die T -Kanten bilden eine Reihe von Bäumen (die
Tiefensuch-Bäume). Die Knotenmengen dieser Bäume sind die
Zusammenhangskomponenten von G .
(b) Die Wurzeln der Bäume sind die jeweils ersten Knoten einer
Zusammenhangskomponente in der Reihenfolge, die in Zeile (2)
benutzt wird.
Gesamt-Laufzeit: O(|V | + |E |): linear!
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
73
Tiefensuche in ungerichteten Graphen
13 6| 5
4| 6
5
3| 7
6
7
5| 1
4
2| 8
12| 10
8
7| 4
8| 3
2
11
12 9| 2
1
1| 9
11| 12
3
9
10| 13
Beobachtung: Jeder Knoten
wird besucht; jede Kante wird in
genau einer Richtung betrachtet
und als Baumkante (T) oder
Rückwärtskante (B) klassifiziert;
die jeweiligen Gegenkanten
werden nicht betrachtet (weil sie
auf gesehen“ gesetzt werden).
”
10 13| 11
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
74
Tiefensuche in ungerichteten Graphen
Kreisfreiheitstest in ungerichteten Graphen.
Zudem: Finden eines Kreises, wenn es einen gibt.
Satz 2.5.3
Nach UDFS(G ) gilt:
B %= ∅ ⇔ G enthält einen Kreis.
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
75
Tiefensuche in ungerichteten Graphen
Beweis:
⇒“: Wenn in Zeile (8) eine neue“ Kante (v , w ) gefunden wird, die zu
”
”
einem aktiven (roten) Knoten w führt, dann bildet diese Kante mit dem
Abschnitt des roten Weges von w nach v zusammen einen Kreis der Länge
≥ 3.
(Es kann nicht sein, dass (w , v ) eine Baumkante ist, da sonst (v , w ) den
Status gesehen“ hätte.)
”
In diesem Moment kann man auch leicht diesen Kreis ausgeben.
⇐“: Wenn B = ∅ ist, dann wird jede Kante von G in einer Richtung
”
Baumkante.
Die Kanten der UDFS-Bäume bilden ungerichtete Bäume und enthalten
alle Kanten von G , also kann G keinen Kreis haben.
#
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
76
Tiefensuche in ungerichteten Graphen
Bemerkung
UDFS auf einen ungerichteten Wald (Vereinigung disjunkter Bäume)
angewendet gibt jeder Komponente eine Wurzel und richtet die Kanten
von dieser Wurzel weg.
Dies ist eine sehr einfache und schnelle Methode (Linearzeit!), einen
ungerichteten Wald zu orientieren“.
”
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
77
Tiefensuche in ungerichteten Graphen
Ergänzung: Zwei alternative Beweise für die schwierigere“
”
Richtung ⇐“ im Satz vom weißen Weg“
”
”
Es gibt hier keinen Grund mehr, sich auf einen Baum zu beschränken, also
betrachten wir den vollen“ DFS-Algorithmus (Folie 25).
”
Satz 2.1.3 ( Satz vom weißen Weg“)
”
w ist (direkter oder indirekter) Nachfahr von v im DFS-Wald ⇔ in dem
Moment, in dem dfs(v ) aufgerufen wird, existiert in G ein Weg
v = u0 , u1 , u2 , . . . , ut = w von v nach w aus Knoten, die alle neu
( weiß“) sind.
”
Definition: Rvneu ist die Menge der zum Zeitpunkt des Aufrufs dfs(v ) von
v aus auf einem weißen Weg“ erreichbaren Knoten.
”
Die einfache Richtung ⇒“ wird bewiesen wie ursprünglich angegeben.
”
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
78
Tiefensuche in ungerichteten Graphen
Beweis 2 für ⇐“: Da durch die T-Kanten die direkte Aufrufbeziehung
”
repräsentiert wird, und durch Wege aus T-Kanten die indirekte
Aufrufbeziehung, genügt es zu zeigen, dass für alle w ∈ Rvneu der Aufruf
dfs(w ) während oder mit dem Aufruf dfs(v ) erfolgt. Dies zeigen wir
indirekt.
Annahme: Es gibt ein w ∈ Rvneu , w %= v , so dass während des Aufrufs
dfs(v ) der Aufruf dfs(w ) nicht erfolgt.
Wir wählen ein solches w und einen Weg v = v0 , v1 , . . . , vt = w in Rvneu ,
mit möglichst kleinem t. Das heißt, dass v = vt−1 gilt oder dfs(vt−1 )
während der Abarbeitung von dfs(v ) aufgerufen wird. Während des
Aufrufs dfs(vt−1 ) wird die Kante (vt−1 , w ) betrachtet. Nach Annahme ist
w dann immer noch neu, das hat aber den Effekt, dass dfs(w ) jetzt
aufgerufen wird, Widerspruch.
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
79
Tiefensuche in ungerichteten Graphen
Beweis 3 für ⇐“:
”
Wir betrachten die Knotenmenge Vvneu aller Knoten, die zum Zeitpunkt des
Aufrufs dfs(v ) neu sind, mit allen Kanten zwischen diesen Knoten. (Alle anderen
Knoten und Kanten werden ausgeblendet.) Diese Knoten und Kanten bilden einen
Teilgraphen Gvneu = (Vvneu , Evneu ) von G .
Nach Satz 2.1.1 gilt folgendes: Wenn man dfs(v ) auf Gvneu aufruft, dann wird im
Verlauf dieses Aufrufs genau für die in diesem Graphen erreichbaren Knoten w die
Prozedur dfs(w ) aufgerufen, also w in den Baum mit Wurzel v eingebaut. Das
sind natürlich genau die Knoten in Rvneu .
Was im DFS-Algorithmus während der Abarbeitung von dfs(v ) tatsächlich
abläuft, sind die von dfs(v ) auf G rekursiv ausgelösten Aufrufe. Hier sind
eventuell Knoten x ∈ V − Vvneu über Kanten (u, x) mit u ∈ Vvneu erreichbar.
Wenn aber im Aufruf dfs(u) eine solche Kante getestet wird, hat dies (außer der
Klassifizierung als C oder B) keinen Effekt, weil der Zielknoten x nicht neu ist;
insbesondere wird kein Aufruf von dfs(x) ausgelöst. Das heißt, dass die Struktur
der Aufrufe genau die gleiche ist wie die auf Gvneu . Daher werden hier ebenfalls
genau die Knoten in Rvneu erreicht.
FG KTuEA, TU Ilmenau
Effiziente Algorithmen – Sommersemester 2012
80
Herunterladen