Algorithmische Graphentheorie Vorlesung 3: Suchalgorithmen in Graphen Babeş-Bolyai Universität, Department für Informatik, Cluj-Napoca [email protected] 7. April 2017 1/43 D URCHSUCHEN VON G RAPHEN Einen Graphen zu durchsuchen bedeutet, dass man von einem gegebenen Knoten aus alle erreichbare Knoten so durchläuft, bzw. durchsucht, dass jeder Knoten nur einmal durchsucht wird. 2/43 B EISPIEL Stellen Sie sich vor, Sie machen einen Ausflug und besuchen einen Irrgarten. Betrachtet man die Wege als Kanten und jede Kreuzung oder Sackgasse als Knoten, so kann man diesen Irrgarten abstrakt als Graphen darstellen. Wie findet man nun den Weg vom Eingang in den Irrgarten zum Ausgang? 3/43 B EISPIEL (2) In dem Beispiel befindet sich der Eingang des Labyrinths bei Knoten 1 und der Ausgang bei Knoten 6. Die sogenannte rechte Hand Regel gibt uns einen Weg wie man in einem Labyrinth seinen Weg findet. Man legt bei Betreten des Labyrinths die rechte (natürlich geht auch die linke) Hand auf die Wand und folgt dann den Wegen ohne die Hand von der Wand zu entfernen. Gerät man in eine Sackgasse oder eine Kreuzung, an der man schon war, so führt dieses Verhalten dazu, dass man den gleichen Weg, den man gekommen ist, wieder zurück geht, bis man eine neue Abzweigung gefunden hat. 4/43 B EISPIEL (3) Abbildung 1: Tiefensuche mit Startknoten 1 und Zielknoten 6 5/43 T IEFENSUCHE - D EPTH F IRST S EARCH (DFS) 6/43 B EMERKUNG Die Tiefensuche durchläuft den Graphen in die Tiefe. Ausgehend vom gegebenen Knoten besucht man dessen ersten noch unbesuchter Nachfolger, danach dessen ersten noch unbesuchten Nachfolger, usw. Wenn ein besuchter Knoten keinen Nachfolger mehr hat, kehrt man zu seinem Vorgänger zurück und sucht bei dessem nächstem unbesuchten Nachfolger weiter. 7/43 T IEFENSUCHE (2) 8/43 B EISPIEL Bemerkung Das Ergebnis für t(v) und B hängt i.d.R. von der Repräsenation des Graphen (z.B. als Adjazenzliste) ab. 9/43 T IEFENSUCHE - VARIANTE 10/43 T IEFENSUCHE - VARIANTE (2) 11/43 T IEFENSUCHE - VARIANTE (3) Intern verwendet der Algorithmus die Farben c(v), mit dessen Hilfe gespeichert wird, ob ein Knoten schon besucht wurde. Hierbei bedeutet c(v) = 0, dass der Knoten v noch weiß, also unbesucht ist. Hat man den Knoten v einmal aufgesucht, so färbt man ihn schwarz, d.h man setzt c(v) = 1. Der rekursive Aufruf des Unterprogramms visit(v) bildet das anfangs besprochene Verhalten nach: Man geht solange weiter zu unbesuchten Knoten, bis man in einer Sackgasse, d.h. einem Knoten, von dem man alle Nachbarn schon besucht hat, landet. Dann zieht man sich zurück auf den letzten Knoten davor, der noch unbesuchte Nachbarn hat, und geht von da aus wieder so weit wie möglich. 12/43 S ATZ Es sei G = (V, E) ein zusammenhängender ungerichteter Graph mit einem Startknoten s oder ein gerichteter Graph mit einer Wurzel s. Dann ist Algorithmus 2 wohldefiniert und findet für alle Knoten v ∈ V einen Weg von s nach v. 13/43 B EWEIS Wir müssen zeigen, dass der Algorithmus nach endlich vielen Aufrufen des Unterprogramms visit(v) abbricht und dass am Ende alle Knoten besucht wurden. Das Unterprogramm visit(v) wird nur für Knoten v mit c(v) = 0 aufgerufen. Da in Zeile 1 des Unterprogramms c(v) = 1 gesetzt wird, kann visit(v) also für jeden Knoten v ∈ V höchstens einmal aufgerufen werden. Daher bricht Algorithmus 2 nach endlich vielen Aufrufen des Unterprogramms visit(v) ab. 14/43 B EWEIS (2) Angenommen, es gäbe nach Abbruch des Algorithmus noch einen Knoten v0 , der nicht besucht wurde, d.h. c(v0 ) = 0. Da G zusammenhängend ist, gibt es einen (gerichteten) Weg P von s nach v0 und auf diesem Weg wurde mindestens s besucht. Folglich gibt es auf dem Weg (mindestens) ein Paar aufeinanderfolgender Knoten v1 und v2 mit c(v1 ) = 1 und c(v2 ) = 0. Abbildung 2: Illustration des Weges P 15/43 B EWEIS (3) Andererseits bedeutet c(v1 ) = 1, dass das Unterprogramm visit(v1 ) aufgerufen wurde. Wegen (v1 , v2 ) ∈ E bzw. {v1 , v2 } ∈ E wurde dann aber auch visit(v2 ) aufgerufen und darin c(v2 ) = 1 gesetzt, ein Widerspruch. Daher gilt nach Abbruch des Algorithmus c(v) = 1 für alle v ∈ V, d.h. alle Knoten wurden besucht. 16/43 B EMERKUNG 17/43 B EMERKUNG (2) 18/43 T IEFENSUCHE - A NWENDUNG Gegeben ein Graph mit n Knoten, gefragt ist, ob dieser Graph zusammenhängend ist oder nicht. Hierfür verwenden wir folgende Prozedur, die auf DFS beruht: Angenommen, die Knoten sind v1 , v2 , . . . , vn . Starte die Suche bei einem beliebigen Knoten und benenne es in Knoten 1 um. Falls dieser Knoten keine adjazente Knoten besitzt, so ist der Graph nicht zusammenhängend. Falls nicht, dann bezeichne einen der adjazenten Knoten als Knoten 2 und markiere die Kante {1, 2} als gelesen. Falls Knoten 2 einen anderen adjazenten Knoten als 1 besitzt, so benenne diesen in Knoten 3 um. 19/43 T IEFENSUCHE - A NWENDUNG (2) Falls Knoten 2 keinen anderen adjazenten Knoten besitzt, so gehe zu Knoten 1 zurück und überprüfe, ob Knoten 1 einen anderen adjazenten Knoten besitzt. Falls die Antwort NEIN ist und n > 2, so ist der Graph unzusammenhängend. Falls die Antwort JA ist, so bezeichne einen dieser Knoten als Knoten 3 und markiere die Kante {2, 3} als gelesen. Usw... Die Prozedur läuft bis wir alle Knoten umnummeriert haben. In diesem Fall ist der Graph zusammenhängend. Falls wir früher zurück zum Knoten 1 gelangen (also weniger als n Knoten wurden umnummeriert), dann ist der Graph unzusammenhängend. 20/43 B EISPIEL Seien v1 , v2 , . . . , v8 Knoten und die Adjazenzmatrix sei gegeben durch 0 1 0 0 0 0 0 1 1 0 1 0 0 1 1 1 0 1 0 1 1 1 0 0 0 0 1 0 0 0 0 0 A= 0 0 1 0 0 0 0 0 . 0 1 1 0 0 0 1 0 0 1 0 0 0 1 0 1 1 0 0 0 0 0 1 0 v2 → 1 Ein adjazenter Knoten ist v7 (s. Matrix). v7 → 2. v6 → 3, v3 → 4, v4 → 5 hat keine andere adjazente Knoten, sodass wir die Prozedur ab Knoten 4 weiter verfolgen. v5 → 6, usw... 21/43 B EISPIEL 22/43 B EISPIEL : S UCHE NACH M R . X Jemand gibt euch einen Brief, der fr einen zufällig ausgewählten Menschen auf der Erde ist: Mr. X. Dieser Brief soll Mr. X erreichen, darf aber immer nur zwischen Menschen weitergegeben werden, die sich kennen. Wie findet ihr einen Weg Mr. X den Brief zukommen zu lassen? Dieses Problem lässt sich mit Hilfe von Graphen wie folgt beschreiben: Man ordnet jedem Menschen auf der Erde einen Knoten zu und fügt zwischen zwei Knoten genau dann eine Kante ein, wenn die zugehörigen Menschen sich kennen. Dann erhält man einen sehr großen ungerichteten Graphen mit ca. 7 Milliarden Knoten und muss einen Weg von dem eigenen Knoten zu dem von Mr. X finden. 23/43 W IE FINDEN WIR EINEN W EG ZU M R . X? Wir wissen zunächst nur, wen wir selbst kennen und auch jeder andere Mensch weiß nur, wen er kennt. Wir überlegen uns zunächst, wen wir alles kennen. Ist Mr. X darunter, so haben wir das Problem gelst. Kennen wir Mr. X nicht, so fragen wir alle Menschen, die wir kennen, ob diese Mr. X kennen. Kennt einer unserer Bekannten Mr. X, so geben wir ihm den Brief und er gibt ihn Mr. X. Kennen unsere Bekannten Mr. X auch nicht, so bitten wir sie, ihre Bekannten zu fragen, ob die ihn kennen und so weiter. 24/43 F INDE EINEN W EG VON K NOTEN 1 ZU K NOTEN 10 25/43 L ÖSUNG Für die Knoten 2, 7 und 11 ist klar, wie ein Weg aussieht, denn es existiert eine direkte Verbindung. Ausgehend vom Knoten 2 lassen sich die Knoten 3 und 5 erreichen, ausgehend von Knoten 7 die Knoten 5 (den wir aber schon hatten), 8 und 12, sowie ausgehend von Knoten 11 der Knoten 8 (zu dem wir ebenfalls schon einen Weg gefunden haben). Betrachtet man nun die Knoten 3, 5, 8 und 12 und deren noch nicht erreichte Nachbarn, so erreicht man die Knoten 4, 6, 9 und 13 und noch eine Runde später schließlich den Knoten 10. Auf diese Weise findet man einen Weg vom Knoten 1 zu Knoten 10, tatsächlich zu allen anderen Knoten im Graphen, und verwendet dabei ausschließlich das Wissen ber die Nachbarn eines Knotens. 26/43 B REITENSUCHE - B READTH F IRST S EARCH (BFS) 27/43 B EMERKUNG Dieser Algorithmus besucht den Graphen in der Breite. Zuerst besucht man den Startknoten, danach all dessen unbesuchte Nachfolger, und nun für jeden gefundenen Nachfolger, wieder alle unbesuchte Nachfolger, usw. Um den Algorithmus zu implementieren, benutzt man eine Warteschlange (queue). 28/43 B REITENSUCHE - B READTH F IRST S EARCH (BFS) (2) 29/43 B REITENSUCHE - B READTH F IRST S EARCH (BFS) (3) 30/43 B REITENSUCHE - B READTH F IRST S EARCH (BFS) VARIANTE 31/43 B REITENSUCHE - B READTH F IRST S EARCH (BFS) VARIANTE (2) Der Algorithmus gibt zwei Vektoren zurück: Die Abstände d(v) geben für jeden Knoten v ∈ V an, wie groß sein Abstand zum Startknoten s ist, d.h. wie viele Kanten der gefundene Weg zwischen den beiden Knoten s und v hat. Der Algorithmus findet zusätzlich auch noch den kürzesten Weg vom Startknoten s zu allen anderen Knoten, d.h. den Weg mit den wenigsten Kanten. Die Anzahl der Kanten in einem solchen kürzesten Weg von s nach v bezeichnet man mit dist(s, v). 32/43 B REITENSUCHE - B READTH F IRST S EARCH (BFS) VARIANTE (3) Der Vorgänger π(v) enthält für jeden Knoten v 6= s den vorletzten Knoten auf dem Weg von s nach v, also den Vorgänger von v auf diesem Weg. Kennt man den Vorgänger π(v), so kann man dessen Vorgänger auslesen und so den Weg zum Startknoten s zurückverfolgen. So erhält man den sogenannten Vorgängergraphen Gπ := (Vπ , Eπ ) mit Vπ := {v ∈ V | π(v) 6= 0} ∪ {s}, Eπ := {(π(v), v) | v ∈ Vπ \ {s}}. 33/43 S ATZ Es sei G = (V, E) ein zusammenhängender ungerichteter Graph mit einem Startknoten s oder ein gerichteter Graph mit einer Wurzel s. Dann ist der Algorithmus wohldefiniert und Zahlen d(v) geben für alle v ∈ V die kürzeste Distanz vom Knoten v zum Startknoten s an. 34/43 B EWEIS Abbildung 3: Illustration des Weges P 35/43 B EWEIS (2) 36/43 B EWEIS (3) 37/43 E IGENSCHAFTEN DER B REITENSUCHE 38/43 B REITEN - UND T IEFENSUCHE BFS UND DFS 39/43 P ROBLEMANALYSE UND E NTWURF DER L ÖSUNG 40/43 BFS 41/43 DFS 42/43 H AUSAUFGABE ! Schreibe das entsprechende C++ Programm Simuliere die beiden Algorithmen aufs Papier mit ein paar Beispielen. 43/43