Interaktives Graphentheorie-Lernen
Interaktives Graphentheorie-Lernen
Guest User
Using app without sign in
Finder für starke Zusammenhangskomponenten
Findet stark zusammenhängende Komponenten mit DFS und Stack
Wählen Sie einen Algorithmus und generieren Sie Schritte, um die Visualisierung zu beginnen
Der Algorithmus von Tarjan findet alle starken Zusammenhangskomponenten (SCCs) eines gerichteten Graphen in einer einzigen Tiefensuche. Eine starke Zusammenhangskomponente ist eine maximale Knotenmenge, in der jeder Knoten jeden anderen über gerichtete Pfade erreichen kann.
Während einer DFS weist der Algorithmus jedem Knoten einen Entdeckungsindex und einen Low-Link-Wert zu, den kleinsten aus seinem Teilbaum über höchstens eine Rückkante erreichbaren Index. Knoten werden beim Besuch auf einen Stapel gelegt. Endet ein Knoten mit einem Low-Link gleich seinem eigenen Index, ist er die Wurzel einer SCC, und der Stapel wird bis zu diesem Knoten geleert, um die Komponente auszugeben. Alles geschieht in O(V + E) in einem Durchlauf.
Die SCC-Zerlegung verdichtet einen gerichteten Graphen zu einem gerichteten azyklischen Graphen, der erste Schritt beim Lösen von 2-SAT, bei der Analyse von Aufrufgraphen in Compilern, der Deadlock-Erkennung und dem Auffinden gegenseitiger Abhängigkeiten in Paketmanagern oder Tabellenkalkulationen. Tarjans Low-Link-Werte sind ein klassisches schweres Interviewthema.
Eine DFS, ein Stapel, zwei Zahlen je Knoten. Die Kernidee: jede starke Zusammenhangskomponente hat eine eindeutige Wurzel, nämlich den zuerst entdeckten Knoten in ihr.
strongconnect(u):
entd[u] = low[u] = ++zeit
stapel.push(u); aufStapel[u] = wahr
für jede Kante (u, v):
wenn v unbesucht:
strongconnect(v)
low[u] = min(low[u], low[v])
sonst wenn aufStapel[v]:
low[u] = min(low[u], entd[v])
// sonst: v liegt in einer fertigen SCC, ignorieren
wenn low[u] == entd[u]: // u ist SCC-Wurzel
Stapel bis einschließlich u abräumen
die abgeräumte Menge ist eine SCCDie aufStapel-Prüfung trennt Tarjan von einem naiven Low-Link-Schema. Eine Kante zu einem besuchten Knoten, der bereits einer abgeschlossenen Komponente zugeordnet ist, sagt nichts über die eigene Komponente aus und muss übersprungen werden; sie einzubeziehen würde zwei tatsächlich getrennte SCCs verschmelzen. Beachte auch die Asymmetrie: eine Baumkante bezieht low[v] ein, eine Rückkante bezieht entd[v] ein, und beides zu verwechseln ist der andere klassische Fehler.
Führe Tarjan auf einem gerichteten Graphen aus, der einen Dreierzyklus, einen Zweierzyklus und einen Knoten enthält, der zu keinem von beiden gehört.
Beispielgraph: Gerichtete Kanten A nach B, B nach C, C nach A, B nach D, D nach E, E nach D und C nach F.
Die endgültigen Low-Link-Werte sind A 1, B 1, C 1, F 4, D 5, E 5, und die Komponenten erscheinen in der Reihenfolge {F}, dann {D, E}, dann {A, B, C}. Zwei Dinge sind bemerkenswert. Die Komponenten werden in umgekehrter topologischer Ordnung der Kondensation ausgegeben, weshalb Tarjan der übliche erste Schritt für 2-SAT ist. Und F, vom Zyklus aus erreichbar, aber ohne Rückweg, bildet korrekt seine eigene Komponente, statt in {A, B, C} aufzugehen.
Zeit: O(V + E) · Speicher: O(V)
Eine einzige Tiefensuche besucht jeden Knoten einmal und betrachtet jede gerichtete Kante genau einmal, was O(V + E) ergibt. Jeder Knoten wird genau einmal auf den Stapel gelegt und einmal entnommen, die Stapeloperationen summieren sich also über den gesamten Lauf zu O(V). Der zusätzliche Zustand besteht aus Entdeckungszeit, Low-Link und Stapelmarkierung je Knoten sowie dem Rekursionsstapel, alles O(V). Tarjan schafft das in einem Durchlauf, während Kosaraju zwei vollständige Durchläufe plus den Aufbau des transponierten Graphen benötigt, weshalb Tarjan in der Praxis meist bevorzugt wird, obwohl beide linear sind.
Alle drei linearen SCC-Algorithmen haben dieselben asymptotischen Kosten, die Wahl geht also um Konstanten, Speicher und die Frage, wie leicht der Code korrekt wird.
| Alternative | Vorzuziehen, wenn | Kosten |
|---|---|---|
| Kosaraju | Du willst den Algorithmus, der sich am leichtesten erklären und implementieren lässt. Zwei DFS-Durchläufe plus eine Transponierte. | O(V + E), zwei Durchläufe |
| Pfadbasierte SCC | Du willst einen Einpassalgorithmus wie Tarjan, aber mit zwei Stapeln statt Low-Link-Arithmetik. | O(V + E) |
| Union-Find | Der Graph ist ungerichtet. Zusammenhangskomponenten sind viel einfacher als starke Zusammenhangskomponenten. | O(E·α(V)) |
| Kondensation plus topologische Sortierung | Du willst den DAG der Komponenten und nicht nur die Komponenten. Tarjan liefert sie bereits in umgekehrter topologischer Ordnung. | O(V + E) |
Den ganzen Artikel lesen: Graph Algorithms and Their Complexity
Verwandte Algorithmen: Kosaraju SCC-Algorithmus, Tiefensuche, Topologische Sortierung