In einem 2-fach zusammenhängenden Graphen ist jedes Knotenpaar durch mindestens zwei kanten- und knotendisjunkte Wege verbunden.
Ein nicht 2-fach zusammenhängender Graph zerfällt in 2-fach Zusammenhangskomponenten, das sind die maximalen 2-fach zusammenhängenden Teilgraphen (siehe Umrahmungen oben).
Die dünnen Kanten stellen ``Rückwärtskanten'' dar, d.h. Kanten, über die zurückgesprungen wird, wenn der Algorithmus in eine Sackgasse gelaufen ist. Solche Kanten wie die gestrichelte Kante sind im Ausgangsgraphen nicht möglich!
Für jede Kante (x,y) gilt: x ist Vorfahre von y oder y ist Vorfahre von x .
`` '': | Die Wurzel ist Artikulationspunkt. |
Die Wurzel hat Knotengrad 2. | |
Die Wurzel hat 2 oder mehrere Söhne. | |
`` '': | Die Wurzel hat 2 oder mehrere Söhne. |
Jeder Sohn der Wurzel ist nach deren Entfernen Wurzel eines Teilbaums. | |
Der Graph zerfällt in 2 oder mehrere Zusammenhangskomponenten. | |
Die Wurzel ist ein Artikulationspunkt. |
Es gibt einen Sohn x von k , der nicht von sich oder seinen Nachfahren einen Vorfahren von k erreichen kann.
`` '': | k sei ein Artikulationspunkt. |
Annahme: Alle Söhne von k erreichen einen Vorfahren von k . | |
Der Graph zerfällt nicht! (Widerspruch zur Voraussetzung) | |
Behauptung | |
`` '': | Von x gehe keine Kante zu einem Vorfahren von k . |
Dieser Vorfahre von k wird durch das Herausnehmen von k von x und dessen Teilbaum vollständig getrennt. | |
Der Graph zerfällt in mehrere Zusammenhangskomponenten. | |
k ist Artikulationspunkt. |
Aus diesen Eigenschaften läßt sich demzufolge ein Verfahren zur Ermittlung der Artikulationseigenschaft eines jeden Knotens ableiten:
Es folgt der Algorithmus, der diesen höchsten erreichbaren Knoten berechnet:
PROCEDURE visit (k: INTEGER): INTEGER;
BEGIN
id := id + 1; val[k] := id; besucht[k] := TRUE; min := val[k];
reset(g[k]);
WHILE NOT endpos(g[k]) DO
x := elem(g[k]);
IF NOT besucht[x] THEN m:= visit(x);
IF m < min THEN min := m;
IF m val[k] THEN Write(4k ist Artikulationspunkt.4); END
ELSE (* Rückkante *)
IF val[x] < min THEN min := val[x]; END;
END;
advance(g[k]);
END (* WHILE *)
RETURN min;
END (* visit *)
Dies ist also ein Beispiel dafür, wie man eine Tiefensuche sinnvoll nutzen kann!