SS10 Effiziente Algorithmen 2. Kapitel: Graphdurchläufe

Ähnliche Dokumente
2.4 Starke Zusammenhangskomponenten in Digraphen

Effiziente Algorithmen

Effiziente Algorithmen

Algorithmen und Datenstrukturen SS09. Foliensatz 17. Michael Brinkmeier. Technische Universität Ilmenau Institut für Theoretische Informatik

Definition Gerichteter Pfad. gerichteter Pfad, wenn. Ein gerichteter Pfad heißt einfach, falls alle u i paarweise verschieden sind.

Algorithmen und Datenstrukturen 15. Vorlesung

Diskrete Strukturen WS 2005/06. Ernst W. Mayr. 27. Januar Fakultät für Informatik TU München

Vorlesung Datenstrukturen

Algorithmus zur topologischen Nummerierung: while V = 0 do nummeriere eine Quelle mit der nächsten Nummer streiche diese Quelle aus V od

Algorithmen und Datenstrukturen

Informatik II, SS 2018

Definition Ein gerichteter Graph G = (V, E) ist ein Graph von geordneten Paaren (u, v) mit u V und v V.

1 DFS-Bäume in ungerichteten Graphen

1 DFS-Bäume in ungerichteten Graphen

4.2 Minimale Spannbäume: Der Algorithmus von Jarník/Prim Definition 4.2.1

(a, b)-bäume / 1. Datenmenge ist so groß, dass sie auf der Festplatte abgespeichert werden muss.

Graphenalgorithmen I. Geschickt Programmieren für den ICPC- Wettbewerb. Felix Weissenberger

Algorithmen und Datenstrukturen SS09. Foliensatz 16. Michael Brinkmeier. Technische Universität Ilmenau Institut für Theoretische Informatik

Informatik II, SS 2014

15. Elementare Graphalgorithmen

Programm heute. Algorithmen und Datenstrukturen (für ET/IT) Übersicht: Graphen. Definition: Ungerichteter Graph. Definition: Ungerichteter Graph

Informatik II, SS 2016

Algorithmen und Datenstrukturen 2-1. Seminar -

WS 2013/14. Diskrete Strukturen

Algorithmen I. Tutorium 1-8. Sitzung. Dennis Felsing

Kapitel IV Minimale Spannbäume

Traversierung 1 / 16. P.F. Stadler & S. Will (Bioinf, Uni LE) ADS 2, V3 23. April / 16

Kapitel IV Minimale Spannbäume

12. Graphen. Notation, Repräsentation, Traversieren (DFS, BFS), Topologisches Sortieren, Ottman/Widmayer, Kap ,Cormen et al, Kap.

ADS: Algorithmen und Datenstrukturen 2

Lösungsvorschlag Hausübung 8

Algorithmen und Datenstrukturen

Informatik II, SS 2016

Diskrete Strukturen Kapitel 4: Graphentheorie (Bäume)

Freie Bäume und Wälder

Einführung in die Informatik 2

Datenstrukturen. Mariano Zelke. Sommersemester 2012

ADS 2: Algorithmen und Datenstrukturen

ADS: Algorithmen und Datenstrukturen 2

Ferienkurs zur algorithmischen diskreten Mathematik Kapitel 1: Grundlagen der algorithmischen Graphentheorie

Programmiertechnik II

Algorithmen und Datenstrukturen 14. Vorlesung

Digraphen, DAGs und Wurzelbäume

\ E) eines Graphen G = (V, E) besitzt die gleiche Knotenmenge V und hat als Kantenmenge alle Kanten des vollständigen Graphen ohne die Kantenmenge E.

Programmiertechnik II

Algorithmen und Datenstrukturen

Keller, Schlangen und Listen. Elementare Datenstrukturen Keller, Schlangen und Listen 1 / 14

Quicksort ist ein Divide-and-Conquer-Verfahren.

ADS: Algorithmen und Datenstrukturen 2

Einheit 11 - Graphen

Zweizusammenhang und starker Zusammenhang

Das Heiratsproblem. Definition Matching

Nachbarschaft, Grad, regulär, Inzidenz

Vorlesung Datenstrukturen

Algorithmen und Datenstrukturen

Wie wird ein Graph dargestellt?

1 Exploration geordneter Wurzelbäume

ADS 2: Algorithmen und Datenstrukturen

Dieser Graph hat 3 Zusammenhangskomponenten

14. Elementare Graphalgorithmen

ADS 2: Algorithmen und Datenstrukturen

Relationen und DAGs, starker Zusammenhang

Breitensuche BFS (Breadth First Search)

Graphenalgorithmen I

Kap. 6.3: Traversieren von Graphen Kap. 6.4: Elementare Graphalgorithmen

12. Graphen. Königsberg Zyklen. [Multi]Graph

Matchings in Graphen. Praktikum Diskrete Optimierung (Teil 5)

NAME, VORNAME: Studiennummer: Matrikel:

Tutoraufgabe 1 (Suchen in Graphen):

VL-14: Graphalgorithmen I. (Datenstrukturen und Algorithmen, SS 2017) Gerhard Woeginger

ADS 2: Algorithmen und Datenstrukturen

Helmut Schauer Educational Engineering Lab Department for Information Technology University of Zurich. Graphen (2)

Vorlesung 3: Graphenalgorithmen. Markus Püschel David Steurer Peter Widmayer. PDF download goo.gl/ym3spq

Effiziente Algorithmen

Exkurs: Graphtraversierung

Graphdurchmusterung, Breiten- und Tiefensuche

ADS: Algorithmen und Datenstrukturen 2

Datenstrukturen (SoSe 12) Klausur (Modulabschlussprüfung)

Algorithmen und Datenstrukturen

ADS: Algorithmen und Datenstrukturen 2

5 Graphen. Repräsentationen endlicher Graphen. 5.1 Gerichtete Graphen. 5.2 Ungerichtete Graphen. Ordnung von Graphen

Graphen und Bäume. A.1 Graphen

Algorithmen und Datenstrukturen Tutorium Übungsaufgaben

10. Übungsblatt zu Algorithmen I im SS 2010

Datenstrukturen. einfach verkettete Liste

Diskrete Strukturen. Hausaufgabe 1 (5 Punkte) Wintersemester 2007/08 Lösungsblatt Januar 2008

MafI I: Logik & Diskrete Mathematik (F. Hoffmann)

= n (n 1) 2 dies beruht auf der Auswahl einer zweielementigen Teilmenge aus V = n. Als Folge ergibt sich, dass ein einfacher Graph maximal ( n E = 2

Algo&Komp. - Wichtige Begriffe Mattia Bergomi Woche 6 7

Algorithmen I - Tutorium 28 Nr. 9

Technische Universität Wien Institut für Computergraphik und Algorithmen Arbeitsbereich für Algorithmen und Datenstrukturen

Lösungen zu Kapitel 5

Graphalgorithmen I. Simon Regnet. May 16, Universität Erlangen. Simon Regnet (Universität Erlangen) Graphalgorithmen I May 16, / 56

Graphen Jiri Spale, Algorithmen und Datenstrukturen - Graphen 1

Seien u, v V, u v. Da G zusammenhängend ist, muss mindestens ein Pfad zwischen u und v existieren.

Algorithmische Graphentheorie

Teil 2: Graphenalgorithmen

Spezifikation und Verifikation Kapitel 2 CTL Model Checking

Algorithmen und Datenstrukturen 13

Transkript:

SS0 Effiziente Algorithmen. Kapitel: Graphdurchläufe Martin Dietzfelbinger April/Mai 00 Kapitel Durchsuchen und Strukturanalyse von Graphen (Ungerichteter) Graph C B W J A R O E G X M FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel Kapitel Durchsuchen und Strukturanalyse von Graphen Erinnerung (siehe http://www.tu-ilmenau.de/fakia/aud_ss09.html,. Foliensatz) Graphen, gerichtete Graphen (Digraphen) Gerichteter Graph 7 Grad, Ingrad, Ausgrad Wege (gerichtet/ungerichtet), einfache Wege Kreise (oder: Zyklen) (gerichtet/ungerichtet) 3 5 9 azyklische Digraphen kreisfreie ungerichtete Graphen: Bäume und Wälder FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 3

Erinnerung Zusammenhängende Graphen Zusammenhangskomponenten Gerichtete Bäume und Wälder Darstellung über Adjazenzmatrix Darstellung über Adjazenzlisten (einfach/doppelt verkettet) Breitensuche (Breadth-First-Search) (http://www.tu-ilmenau.de/fakia/aud_ss09.html, 7. Foliensatz). Einfache Tiefensuche in Digraphen 3 5 3 3 7 9 0 Eingabeformat: Digraph G =(V, E), Knotenmenge V = {,..., n}, Adjazenzlisten- oder Adjazenzmatrixformat, geordnete Kantenlisten. Ziele: Besuche alle Knoten und Kanten. Sammle Strukturinformation. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 5 Tiefensuche (Depth-First-Search) in Graphen G =(V, E). O.B.d.A.: V = {,..., n}. Zweck: Gehe von Knoten v 0 aus, finde alle von v 0 aus erreichbaren Knoten. Realisierung: Rekursive Prozedur dfs(v). Besuche Knoten v (Aktion an diesem Knoten). Betrachte die Nachbarn w,..., w outdeg(v) von v nacheinander, aber: Sobald neuer Knoten w entdeckt wird, starte sofort dfs(w). (Weitere Nachbarn von v kommen später dran.) Vorwärtsgehen hat Vorrang! Effekt: Die Folge der entdeckten Knoten geht vorrangig in die Tiefe. Man muss verhindern, dass Knoten v mehrfach entdeckt wird. Dazu: Statusinformation neu, aktiv, fertig. v neu : weiß noch nie gesehen v v aktiv : rot dfs(v) gestartet, noch nicht beendet fertig : grau dfs(v) beendet Status wird in einem Array status[.. n] gehalten ein Eintrag pro Knoten. Parallel zu (oder Teil von) Knotenarray nodes[.. n] Initialisierung: Alle Knoten sind neu. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 7

Knoten werden in der Reihenfolge der Entdeckung durchnummeriert: dfs num[.. n]. Tiefensuch-Nummerierung. Mitzählen: in dfs count, mit 0 initialisiert. dfs-visit(v): Aktion an v bei Entdeckung, anwendungsabhängig. Zunächst: Tiefensuche in gerichteten Graphen/Digraphen. Einfachstversion, wird später ausgebaut. Algorithmus dfs(v) ( Tiefensuche an v, rekursiv ) ( darf nur für v mit status[v] = neu aufgerufen werden ) () dfs count++; () dfs num[v] dfs count; (3) dfs-visit(v); ( Aktion an v bei Erstbesuch ) () status[v] aktiv ; (5) für jeden Nachfolger w von v (Adjazenzliste!) tue: () if status[w] = neu ( w wird entdeckt! ) then (7) dfs(w); () status[v] fertig. Tiefensuche von v 0 aus: Initialisiere alle Knoten als neu und dfs count 0. Rufe dfs(v 0 ) auf. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 9 3 5 3 3 7 9 0 3 5 3 3 7 9 0 Roter Weg : () (Aktive dfs(v)-aufrufe.) Roter Weg : (,, ) FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 0 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 0

3 5 Roter Weg : () 3 3 7 9 0 Beobachtung über dfs(v 0 ) : Für jeden von v 0 erreichbaren Knoten v wird dfs(v) genau einmal aufgerufen. Beweis: Sobald dfs(v) aufgerufen wird, wird status[v] aktiv gesetzt, nie mehr zurück auf neu. Aufruf erfolgt nur für neue Knoten. Daher: maximal ein Aufruf. Sei nun (v 0,v..., v m = v) einfacher Weg von v 0 nach v. Durch Induktion über i =0,,..., m zeigt man: dfs(v i ) wird aufgerufen. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 0 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel Beobachtung über dfs(v 0 ) : Sei V 0 = {v v 0 v}. (Von v 0 aus erreichbare Knoten.) Jeder Knoten v V 0 {v 0 } wird von einem eindeutig bestimmten Knoten w aus entdeckt; diesen nennen wir p(v), den Vorgänger von v. Der Aufruf dfs(v) erfolgt während der Abarbeitung des Aufrufs dfs(p(v)). Insbesondere: dfs(p(v)). dfs(v) beginnt nach und endet vor 3 3 5 3 3 7 9 0 5 Rot: Pfeile von p(v) zu v: Entdeckungsrichtung. Wegen der Eindeutigkeit des Vorgängers: Baumstruktur. v 0 ist die Wurzel. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 3

Beobachtung 3 über dfs(v 0 ) : Der Zeitaufwand für die Bearbeitung eines Aufrufs dfs(v) ist (ohne die rekursiven Aufrufe) O() + O(outdeg(v)). Der Zeitaufwand für dfs(v 0 ) ist linear, nämlich ( ) O ( + outdeg(v)) = O( E 0 ), v V 0 wo V 0 die Menge der von v 0 aus erreichbaren Knoten, E 0 die Menge der von v 0 aus erreichbaren Kanten ist. (Beachte: V 0 E 0 +.) Strukturinformation : Mit Tiefensuche in G lässt sich in Zeit O( V + E 0 ) die Menge V 0 der von v 0 aus erreichbaren Knoten ermitteln. (O( V ) wegen der Initialisierungskosten.) Für v V definieren wir: R v = {w V v w}. E Rv sei die Menge der Kanten, die von Knoten in R v ausgehen. 3 3 5 3 3 7 9 0 5 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 5 Mit Tiefensuche in G, gestartet von jedem Knoten nacheinander, lassen sich in Zeit O( v V E R v )=O( V E ) alle Mengen R v, v V, ermitteln. (Nach Aufruf dfs(v) kann man mit Hilfe der Liste für R v in Zeit O( R v ) das status-array wieder auf neu setzen.) Definition Die transitive Hülle eines Digraphen G ist der Graph TH(G) =(V, E ) mit Kantenmenge E = {(v, w) v, w V, v G w} = ({v} R v ). v V Obige Beobachtung besagt, dass man mit wiederholter Tiefensuche die Kantenmenge E in Zeit O( v V E R v ) = O( V E ) berechnen kann. Strukturinformation : 3 3 5 3 3 7 9 0 5 Die Kanten (p(v),v) bilden einen (gerichteten) Baum mit Wurzel v 0 und Knotenmenge V 0, den Tiefensuch-Baum T dfs (v 0 ). (w, v) ist Kante in T dfs (v 0 ) dfs(v) wird direkt aus dfs(w) aufgerufen. Weg im Tiefensuch-Baum entspricht indirekter Aufrufbeziehung. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 7

3 3 5 3 3 3 5 3 3 7 9 0 5 7 9 0 Die Tiefensuch-Nummern nummerieren die Knoten im Baum in Präorder-Art: erst die Wurzel, dann nacheinander rekursiv die Unterbäume. Zu jedem Zeitpunkt bilden die aktiven Knoten einen Weg (den roten Weg ) im Tiefensuch-Baum, Startpunkt v 0, Endpunkt ist der Knoten, in dessen dfs(v) -Aufruf eben gearbeitet wird. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 9??? Wann sitzt w in T dfs (v 0 ) im Unterbaum mit Wurzel v???? Wann wird dfs(w) aufgerufen, während v aktiv ist? Satz.. ( Satz vom weißen Weg ) w ist ein (direkter oder indirekter) Nachfolger von v im Tiefensuchbaum T dfs (v 0 ), in dem Moment, in dem dfs(v) aufgerufen wird, existiert ein Weg v = u 0,u,u,..., u t = w aus lauter neuen Knoten (ein Weg von v nach w aus weißen Knoten ). Beispiel: dfs() startet. 3 5 7 9 0 3 3 Knoten ist von aus erreichbar, aber nicht auf einem weißen Weg Knoten nicht in Tiefensuchbaum unter. Knoten 3, 7, sind auf weißen Wegen erreichbar diese Knoten sitzen im Tiefensuchbaum unter. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 0 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel

Beweis: : 3 3 5 3 3 7 9 0 5 Sei w in T dfs (v 0 ) Nachfolger von v. Wir nehmen den Weg, der in T dfs (v 0 ) von v nach w führt: v = u 0,u,u,..., u t = w. (Beispiel: (,, 7).) Dann wird dfs(u ) nach dfs( u 0 ) aufgerufen, dfs(u ) nach }{{} v dfs(u ), usw. also sind im Moment des Aufrufs dfs(v) alle Knoten v = u 0,u,u,..., u t = w noch neu. Beweis des Satzes: : Sei zum Zeitpunkt des Aufrufs dfs(v) v = u 0,u,u,..., u t = w, t, ein einfacher Weg aus neuen ( weißen ) Knoten. (Beispiel: (, 7).) Achtung: Es ist nicht gesagt, dass genau dieser Weg im Baum T dfs (v 0 ) auftaucht. O.B.d.A.: i>0. (Sonst Aussage trivial.) Wir zeigen durch Induktion über i =0,,..., t: Behauptung: Der Aufruf dfs(u i ) beginnt, bevor dfs(v) endet. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 3 I.Beh.: Der Aufruf dfs(u i ) beginnt, bevor dfs(v) endet. I.A.: i =0: u 0 = v; dfs(v) beginnt, bevor dfs(v) endet. I.V.: i, und dfs(u i ) beginnt, bevor dfs(v) endet. I.S.: Aus I.V. folgt: dfs(u i ) endet auch spätestens wenn dfs(v) endet. ( ) (Grundprinzip bei geschachtelten Prozeduraufrufen.) Im Aufruf dfs(u i ) wird die Kante (u i,u i ) angesehen.. Fall: u i ist aktiv oder fertig. Wegen ( ): dfs(u i ) hat begonnen, bevor dfs(v) endet.. Fall: u i ist neu. Dann wird dfs(u i ) direkt aus dfs(u i ) aufgerufen. Wegen ( ): dfs(u i ) beginnt, bevor dfs(v) endet. Wenn wir die Behauptung für i = t anwenden, folgt: Der Aufruf dfs(w) beginnt, bevor dfs(v) endet. Weil w beim Start des Aufrufs dfs(v) neu war und w v: dfs(w) beginnt nach dfs(v) und endet, bevor dfs(v) endet. Daher: Die Folge w, p(w),p(p(w)),p(p(p(w))),... erreicht v. Umgedreht gelesen, ist dies ein Weg von v nach w in T dfs (v 0 ). FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 5

Globale Tiefensuche in Digraph G: Alle Knoten besuchen. Algorithmus DFS(G) ( Tiefensuche in G =(V, E) ) () dfs count 0; () for v from to n do status[v] neu; (3) for v from to n do () if status[v] = neu then (5) dfs(v); ( starte Tiefensuche von v aus ) Zu Zeilen ()/(5): dfs count wird weitergezählt. Zu Zeilen (), (): Die status[v]-werte werden von den dfs-aufrufen in Zeile (5) verändert; sie haben also beim Wieder-Lesen in der zweiten Schleife nicht unbedingt immer noch den Initialisierungs-Wert neu. 3 7 9 3 5 3 3 7 9 0 5 Tiefensuchwald mit dfs-nummern. Pfeile von p(v) zu v: Entdeckungsrichtung 0 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 7 DFS(G) erzwingt, dass für jeden Knoten v in G irgendwann einmal dfs(v) aufgerufen wird. Daher werden auch alle Kanten, die aus v herausführen, angesehen. Gesamt-(Zeit-)Aufwand: O( + outdeg(v)) für Knoten v. Insgesamt: ( ) O ( + outdeg(v)) = O( V + E ) =O(n + m). v V Satz.. Der Zeitaufwand von DFS(G) ist O( V + E ). (Sogar: Θ( V + E ), da jeder Knoten und jede Kante betrachtet wird.) Bemerkung: Bei DFS entstehen mehrere Bäume, die zusammen den Tiefensuchwald bilden. Vorsicht: Wenn ein Baum im Tiefensuchwald Wurzel v hat, so ist nicht gesagt, dass dieser Baum alle von v aus erreichbaren Knoten enthält. (Dies gilt nur für den ersten der Bäume.) 3 7 9 3 5 7 9 0 3 3 5 Beispiel: Es gilt 5, aber ist nicht im Baum unter 5. 0 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 9

3 7 9 3 5 3 3 7 9 0 5 0 Beweis: : Sei v / W v. Dann kann v von keinem Aufruf dfs(w) mit w < v erreicht werden, also ergibt der Test if status[v] = neu in Zeile () true, und der Aufruf dfs(v) erfolgt. Der Satz vom weißen Weg gilt auch für den Tiefensuchwald. Wir definieren: W v = {u {,..., n} w v : w u} Satz..3 v wird Wurzel eines Baums im Tiefensuch-Wald v/ W v. In diesem Fall: Baum mit Wurzel v hat als Knoten die Elemente der Menge W v W v (erreichbar von v aus, aber von keinem vorherigen Knoten). FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 30 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 3 : Sei v W v, also v von w < v aus erreichbar. Wähle w {,..., n} minimal mit dieser Eigenschaft. Wähle Weg w = u 0,..., u t = v. Minimalität keines der u i, 0 i t, ist von einem x<w erreichbar. Test status[w] = neu? in () liefert true, dfs(w) wird aus DFS(G) aufgerufen. In diesem Moment sind alle Knoten auf dem Weg w = u 0,..., u t = v noch neu. Satz... (Satz vom weißen Weg) v wird Nachfahr von w im Tiefensuch-Wald v ist keine Wurzel.. Volle Tiefensuche in Digraphen Wir bauen dfs(v) und DFS(G) aus, so dass die Kanten von G in vier Teilmengen T, B, F, C eingeteilt werden: T : Baumkanten die Kanten des Tiefensuchwaldes; B: Rückwärtskanten (v, w) ist Rückwärtskante, wenn v Nachfahr von w im Tiefensuchwald ist; F : Vorwärtskanten (v, w) ist Vorwärtskante, wenn v Vorfahr von w im Tiefensuchwald ist; C: Querkanten (v, w) ist Querkante, wenn der gesamte Unterbaum von w fertig abgearbeitet ist, wenn die Kante (v, w) getestet wird (d.h.: w liegt im Tiefensuchwald gemäß Präorder- und gemäß Postorder-Reihenfolge vor v). FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 3 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 33

Zudem nummerieren wir die Knoten v V in der Reihenfolge durch, in der die dfs(v)-aufrufe beendet werden. Diese Nummern heißen fin-nummern oder f-nummern: f num(v). Der Wertebereich der f-nummern ist {,,..., V }. Die folgende Prozedur darf nur für v mit status[v] = neu aufgerufen werden. Algorithmus dfs(v) ( Tiefensuche in v, voll ausgebaut ) () dfs count++; () dfs num[v] dfs count; (3) dfs-visit(v); ( Aktion an v bei Erstbesuch ) () status[v] aktiv ; (5) für jeden Nachfolger w von v (Adjazenzliste!) tue: (). Fall: status[w] = neu : T T {(v, w)}; dfs(w); (7). Fall: status[w] = aktiv : B B {(v, w)}; () 3. Fall: status[w] = fertig dfs num[v] < dfs num[w]: F F {(v, w)}; (9). Fall: status[w] = fertig dfs num[v] > dfs num[w]: C C {(v, w)}; (0) f count++; () f num[v] f count; () fin-visit(v); ( Aktion an v bei letztem Besuch ) (3) status[v] fertig. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 3 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 35 Tiefensuche von v 0 aus entdeckt den von v 0 aus erreichbaren Teil des Graphen: Initialisierung: dfs count 0; f count 0. Alle Knoten sind neu ; Mengen T, B, F, C sind leer. Rufe dfs(v 0 ) auf. Tiefensuche für den ganzen Graphen: DFS(G) wie vorher, nur mit der voll ausgebauten dfs-prozedur, und der Initialisierung von f count und T, B, F, C. Algorithmus DFS(G) ( Tiefensuche in G =(V, E), voll ausgebaut ) () dfs count 0; () f count 0; (3) T ; B ; F ; C ; (3) for v from to n do status[v] neu; () for v from to n do (5) if status[v] = neu then () dfs(v); ( starte Tiefensuche von v aus ) / C / 3 / 7 / 9 /0 3 5 3 3 7 9 0 /5 5 / /3 /7 0 /9 T Ergebnis der Kantenklassifikation am Beispiel-Digraphen. Klar: Alle Laufzeitaussagen für die einfache dfs-prozedur behalten weiter Gültigkeit. B F FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 3 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 37

Beobachtung : Jede Kante (v, w) wird genau einmal betrachtet und daher genau in eine der Mengen T, B, F und C eingeordnet. Beobachtung : Die dfs-nummern entsprechen einem Präorder-Durchlauf, die f-nummern einem Postorder-Durchlauf durch die Bäume des Tiefensuch-Waldes. Beobachtung 3: Wenn dfs(w) nach dfs(v) beginnt und vor dfs(v) endet, also dfs(w) (indirekt) von dfs(v) aus aufgerufen wird, dann gilt: (a) dfs num[v] < dfs num[w] und f num[v] > f num[w]; (b) v ist Vorfahr von w im Tiefensuch-Wald. Konsequenz: Die Vorfahr-Nachfahr-Relation im Tiefensuch- Wald lässt sich in Zeit O() testen, wenn die dfs- und die f-nummern bekannt sind. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 3 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 39 Satz.. Die Tiefensuch-Prozedur klassifiziert die Kanten korrekt. Beweis: Sei (v, w) eine beliebige Kante in G.. Fall: dfs(w) wird direkt aus dfs(v) aufgerufen. Dann ist (v, w) Baumkante und wird richtig als T klassifiziert.. Fall: Die Untersuchung der Kante (v, w) in dfs(v) ergibt, dass w aktiv ist. Dann liegt w auf dem roten Weg von der Wurzel des Tiefensuchbaums zu v, ist also Vorfahr von v (oder gleich v Schleifen sind nicht verboten). Daher ist (v, w) Rückwärtskante und wird richtig als B klassifiziert. 3. Fall: Die Untersuchung der Kante (v, w) in dfs(v) ergibt, dass w fertig und dfs num[v] < dfs num[w] ist. Dann wird f num[v] > f num[w]. Also ist nach Beobachtung 3 w Nachfahr von v im Tiefensuchwald, also ist (v, w) Vorwärtskante und wird richtig als F klassifiziert.. Fall: Die Untersuchung der Kante (v, w) in dfs(v) ergibt, dass w fertig und dfs num[v] > dfs num[w] ist. Dann ist die Untersuchung von w und all seinen Nachfahren im Wald abgeschlossen, bevor v begonnen wird. Daher ist (v, w) Querkante und wird richtig als C klassifiziert. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 0 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel

.3. Kreisfreiheitstest und topologische Sortierung Satz.3. (a) Nach Aufruf von DFS(G) gilt: G enthält einen Kreis B. (b) Nach Aufruf von dfs(v) gilt: Der von v aus erreichbare Teil R v = {w V v w} von G enthält einen Kreis B. Beweis des Satzes (a): : Wenn DFS(G) eine B-Kante (v, w) findet, dann ist v der vorderste Knoten des roten Weges, und w liegt auf dem roten Weg. Also ist w = u 0, u,..., u t = v in G, t 0 ein Abschnitt des roten Weges. Zusammen mit der Kante (v, w) erhalten wir einen Kreis. Spezialfall: v = w, t =0: Schleife. Wird als Kreis erkannt. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 3 Beweis des Satzes (a): : Nun sei B =. Für eine Kante (v, w) gibt es dann nur noch drei Fälle:. Fall: (v, w) ist Baumkante. Dann ist f num[v] > f num[w]../3. Fall: (v, w) ist Vorwärtskante oder Querkante. Dann ist w fertig, während an v noch gearbeitet wird, also ist f num[v] > f num[w]. Wenn also u 0,..., u t ein Weg in G der Länge t ist, so nehmen entlang dieses Weges die f-nummern strikt ab. Daher kann auf keinen Fall u 0 = u t sein. Also enthält G keinen Kreis. Definition Ein gerichteter Graph (Digraph) ohne Kreise heißt ein gerichteter azyklischer Graph ( directed acyclic graph dag). Wollen: Knoten in einem azyklischen Digraphen so anordnen, dass alle Kanten von links nach rechts laufen. Definition Sei G =(V, E) ein azyklischer Digraph. Eine topologische Sortierung (oder topologische Anordnung) der Knoten in V ist eine Bijektion π : V {,..., n}, so dass (v, w) E π(v) < π(w) gilt. Man stellt sich die Knoten in der Reihenfolge π (), π (),..., π (n) vor; dann laufen die Kanten alle von links nach rechts. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 5

0 3 5 3 3 7 9 0 5 3 7 9 Ein azyklischer Digraph mit f-nummern. 5 0 9 0 9 7 5 3 Derselbe Graph, linear angeordnet. Permutation dazu: v 3 5 7 9 0 π(v) 5 7 0 3 9 7 3 DFS(G) findet unmittelbar eine topologische Sortierung! (Natürlich nur in azyklischen Digraphen.) Idee: Wir haben oben gesehen, dass die f-nummern entlang jeder Kante (v, w) strikt fallen; außerdem sind die f-nummern eine Bijektion. Definiere: π(v) := (n + ) f num(v). Laufzeit/Kosten zur Ermittlung einer topologischen Sortierung: O( V + E ), linear. Satz.3. DFS(G) (in der ausführlichen Version) testet Digraphen auf Azyklizität und findet gegebenenfalls eine topologische Sortierung von G, in Zeit O( V + E ). FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 7 Anwendung : V : Menge von Tasks (für einen Computer, für eine Maschine). E V V : Zeitliche Abhängigkeiten. (v, w) E heißt: Task v muss beendet sein, bevor Task w beginnt. Topologische Sortierung: Eine mögliche Ausführungsreihenfolge. Bei Parallelverarbeitung: viel komplexere Aufgabe! Anwendung : V : Menge von Tasks (für einen Computer, für eine Maschine), mit Laufzeiten c(v). E V V : Zeitliche Abhängigkeiten wie vorher. Kritischer Pfad : Folge v 0,v,..., v r von Tasks mit (v 0,v ),..., (v r,v r ) E und c(v 0 )+c(v )+... + c(v r ) maximal. Ein kritischer Pfad bestimmt die minimal mögliche Gesamt- Ausführungszeit. Aufgabe: Bestimme kritischen Pfad, in Zeit O( V + E ). FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 9

Lösung: Ermittle topologische Sortierung von (V, E). O.B.d.A. gilt (v, w) E v < w. (Umbenennen!) Finde iterativ für v =,..., n den frühesten Beendigungszeitpunkt t(v) und Vorgänger p(v) auf einem kritischem Pfad in {,..., v}. p() existiert nicht; t() = c(). I.V.: t(),..., t(v ) schon ermittelt. Schritt v: { c(v) + max{t(w) (w, v) E}, falls eine Kante (w, v) existiert, t(v) := c(v), sonst. Vorgänger p(v): Ein w mit (w, v) E und maximalem t(w), wenn es eine solche Kante gibt, undefiniert, falls nicht. Ausgabe: v mit maximalem t(v) und die Folge v, p(v),p(p(v)),... bis zum ersten Knoten w mit undefiniertem p(w).. Starke Zusammenhangskomponenten in Digraphen Definition Zwei Knoten v und w in einem Digraphen G heißen äquivalent, wenn v w und w v gilt. Notation: v w. Überlege: (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. Definition Die Äquivalenzklassen zur Relation heißen starke Zusammenhangskomponenten von G. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 50 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 5 Starke Zusammenhangskomponenten in Digraphen Beispiel: 5 Komponenten, Tiefensuchbäume. 5 3 9 7 0 3 Lemma.. Bei der Ausführung von DFS(G) gilt: Wenn C V eine starke Zusammenhangskomponente ist, dann liegen die Knoten von C alle in einem Tiefensuchbaum. M.a.W.: Jeder Tiefensuchbaum ist eine starke Zsh.- Komponente oder lässt sich in mehrere starke Zsh.- Komponenten zerlegen. Beweis: Betrachte den ersten Knoten v C, für den dfs(v) aufgerufen wird. Von v aus sind alle w C auf einem Weg in C erreichbar (Definition s.z.k.), und alle Knoten auf diesen Wegen sind noch neu. (nach dem Satz vom weißen Weg ) Alle Knoten von C werden Nachfahren von v im Tiefensuchbaum. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 5 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 53

Um mit Tiefensuche die starken Zusammenhangskomponenten zu finden, muss man verhindern, dass in einem Baum mehrere solche Komponenten sitzen. Trick : Benutze Umkehrgraphen G R, der durch Umkehren aller Kanten in G entsteht. Beobachtung: G R hat dieselben starken Zusammenhangskomponenten wie G. (Die Kreise in den beiden Graphen sind dieselben, nur mit umgekehrter Durchlaufreihenfolge.) 5 3 5 3 9 7 9 7 0 0 3 3 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 5 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 55 Eine günstige Wahl der Reihenfolge der Startpunkte für die Tiefensuche in G R verhindert, dass versehentlich Knoten einer anderen starken Zusammenhangskomponente erreicht werden. Trick : Verwende fin-nummern-sortierung von G. 5 7 5 3 3 3 9 7 3 0 9 0 Graph G mit starken Zsh.-Komponenten und f-nummern. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 5 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 57

7 5 9 3 0 3 3 7 Graph G R mit starken Zsh.-Komponenten und f-nummern für G. Untersuche Knoten gemäß fallenden f-nummern auf Eigenschaft neu. Von aus wird eine s.z.k. erreicht, von 9 aus die nächste, von 5 aus die nächste, von aus die nächste, von 3 aus die letzte. Keine s.z.k. wird versehentlich betreten. 3 9 0 5 Algorithmus Strong Components(G) Eingabe: Digraph G =(V, E) Ausgabe: starke Zusammenhangskomponenten von G () Berechne die f-nummern mittels DFS(G); () Bilde Umkehrgraphen G R durch Umkehren aller Kanten in G; (3) Führe DFS(G R ) durch; Knotenreihenfolge: f-nummern aus () absteigend () Ausgabe: Die Knotenmengen der Tiefensuchbäume aus (3). Satz.. (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 SS0 Kapitel 5 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 59 Beweis von Teil (a): Wir wissen schon, dass jede starke Zsh.-Komponente C komplett in einem DFS-Baum der Tiefensuche in G R enthalten ist. Zu zeigen: Kein DFS-Baum der G R -Tiefensuche enthält mehrere Komponenten. Es sei C V eine beliebige starke Zusammenhangskomponente von G bzw. von G R. v C sei der Knoten mit maximaler f-nummer (aus der G-Tiefensuche). Behauptung: In G R ist v von keinem Knoten mit größerer f-nummer aus erreichbar. [Dann folgt aus Satz..3 (Knotenmengen der DFS- Bäume) und der besonderen Durchlaufreihenfolge fallende f-nummern, dass im zweiten DFS-Durchlauf v Wurzel eines DFS-Baums wird. Da C beliebig war, enthält also jede starke Zusammenhangskomponente eine DFS-Baum-Wurzel, also müssen diese Komponenten jede für sich einen Baum bilden.] FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 0 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel

Behauptung: In G R ist v von keinem Knoten w mit größerer f-nummer aus erreichbar. Äquivalent: Wenn es in G R einen Weg von w nach v gibt, dann gilt f-num(w) f-num(v). Beweis dieser Formulierung: Sei w = v t,v t,v t,..., v,v 0 = v ein Weg in G R. O.B.d.A.: v w. Das heißt: v = v 0,v,..., v t,v t = w ist ein Weg in G. }{{} =p Wir betrachten nun die (erste) Tiefensuche in G.. Fall: Wenn dfs(v) startet, ist der gesamte Weg p weiß. Dann wird w Nachfahr von v im DFS-Baum, also ist f-num(w) < f-num(v).. Fall: Wenn dfs(v) startet, liegt auf dem Weg p ein roter Knoten v i. Dann ist v i Vorfahr von v im DFS-Baum, und von v zu v i führt der erste Teil des Weges p: also liegen v und v i auf einem Kreis. Also ist v v i, also v i C. Andererseits ist f-num(v i ) > f-num(v), im Widerspruch zur Wahl von v. Der. Fall kann also gar nicht eintreten. 3. Fall: Wenn dfs(v) startet, liegt auf dem Weg p ein grauer Knoten v i v. Nach der dfs-prozedur und Fall gilt: Wenn v i grau ist und i < t, dann ist auch v i+ grau. Also ist w grau, wenn dfs(v) startet. Daraus: f-num(w) < f-num(v). FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 3.5 Tiefensuche in ungerichteten Graphen : Einfacher als Tiefensuche in gerichteten Graphen. Zweck: v: r w t Zusammenhangskomponenten finden Spannbaum für jede Zusammenhangskomponente finden Kreisfreiheitstest w: t u v s (Diese einfachen Aufgaben wären auch auch von Breitensuche zu erledigen.) Komplexere Erweiterungen, z. B. Zweifach-Zusammenhangskomponenten, erfordern DFS. (Lit.: Sedgewick, Kap. 5.) n: Adjazenzlistendarstellung mit Querverweisen. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 5

Darstellung von ungerichteten Graphen: Adjazenzlistendarstellung mit Querverweisen. Knotenarray: nodes[..n]. Zu Knoten v gibt es eine lineare Liste L v 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 L w (und natürlich auch umgekehrt). Wir können an Kanten Markierungen anbringen. Wir stellen sicher, dass nach Benutzung der Kante (v, w) in Richtung von v nach w die umgekehrte Richtung nicht mehr benutzt wird ( gesehen ). Klassifizierung in T -Kanten und B-Kanten. Algorithmus udfs(v) ( Tiefensuche von v aus, rekursiv ) ( nur für v mit status[v] = neu aufrufen ) () dfs count++; () dfs num[v] dfs count; (3) dfs-visit(v); ( Aktion an v bei Erstbesuch ) () status[v] aktiv ; (5) für jede neue Kante (v, w) (Adjazenzliste!) tue: () setze Gegenkante (w, v) auf gesehen ; (7). Fall: status[w] = neu: T T {(v, w)}; udfs(w); (). Fall: status[w] = aktiv: B B {(v, w)}; (9) f count++; (0) f num[v] f count; () fin-visit(v); ( Aktion an v bei letztem Besuch ) () status[v] fertig. FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 7 Globale Tiefensuche in (ungerichtetem) Graphen G: Algorithmus UDFS(G) ( Tiefensuche in G =(V, E) ) () dfs count 0; () f count 0; (3) for v from to n do status[v] neu; () T ; B ; (5) for v from to n do () if status[v] = neu then (7) udfs(v); ( starte Tiefensuche von v aus ) 5 5 7 0 9 0 3 Ungerichteter Graph mit Baum- und Rückwärtskanten sowie der dfs-nummerierung. 3 9 7 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 9

Satz.5. udfs(v 0 ) werde aufgerufen. Dann gilt: (a) udfs(v 0 ) entdeckt genau die Knoten in der Zusammenhangskomponente von v 0. (b) Die Kanten (v, w), wo udfs(w) unmittelbar aus udfs(v) aufgerufen wird, bilden einen (gerichteten) Baum mit Wurzel v 0. ( 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 + E v0 ), wo E v0 die Menge der Kanten in der Zusammenhangskomponente von v 0 ist. Beweis: Ähnlich zum gerichteten Fall. Satz.5. 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 () benutzt wird. Gesamt-Laufzeit: O( V + E ): linear! FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 70 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 7 5 5 7 7 Kreisfreiheitstest in ungerichteten Graphen. Zudem: Finden eines Kreises, wenn es einen gibt. 3 0 9 3 9 Satz.5.3 Nach UDFS(G) gilt: B G enthält einen Kreis. 0 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). FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 7 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 73

Beweis: : Wenn in Zeile () 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. 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 SS0 Kapitel 7 FG KTuEA, TU Ilmenau Effiziente Algorithmen SS0 Kapitel 75