\( \newcommand{\data}{\textnormal{data}} \newcommand{\lower}{\textnormal{lower}} \newcommand{\upper}{\textnormal{upper}} \newcommand{\array}{\textnormal{array}} \newcommand{\depth}{\textnormal{depth}} \newcommand{\height}{\textnormal{height}} \newcommand{\BST}{\textnormal{BST}} \newcommand{\floor}[1]{\left\lfloor #1 \right\rfloor} \newcommand{\ceil}[1]{\left\lceil #1 \right\rceil} \newcommand{\lognpone}{\ceil{\log_2(n+1)}} \newcommand{\bitsize}{\textnormal{bitSize}} \newcommand{\mult}{\textnormal{mult}} \newcommand{\inneighbors}{\textnormal{inNeighbors}} \newcommand{\outneighbors}{\textnormal{outNeighbors}} \newcommand{\neighbors}{\textnormal{neighbors}} \newcommand{\indeg}{\textnormal{indeg}} \newcommand{\outdeg}{\textnormal{outdeg}} \newcommand{\scc}{\textnormal{scc}} \newcommand{\R}{\mathbb{R}} \newcommand{\val}{\textnormal{val}} \newcommand{\dist}{\textnormal{dist}} \newcommand{\flows}{\textnormal{flows}} \newcommand{\Z}{\mathbb{Z}} \)

Ein fundamentales Problem für Graphen ist das Berechnen seiner Zusammenhangskomponenten.

Definition Sei $G = (V,E)$ ein Graph. Für zwei Knoten $u, v \in V$ schreiben wir $u \rightsquigarrow v$, wenn es einen Pfad von $u$ nach $v$ gibt. Die Relation $\rightsquigarrow$ ist reflexiv und transitiv. Wenn $G$ ungerichtet ist, dann ist $\rightsquigarrow$ eine symmetrische Relation und wir schreiben $u \leftrightsquigarrow v$. In diesem Falle ist $\leftrightsquigarrow$ also eine Äquivalenzrelation und partitioniert die Knotenmenge in Zusammenhangskomponenten $C_1, \dots, C_k$, also

  • $V = C_1 \cup \dots \cup C_k$,
  • $C_i \cap C_j = \emptyset$ für $i \ne j$
  • Wenn $u \in C_i$ und $v \in C_j$ dann gilt $u \leftrightsquigarrow v$ wenn $i=j$ ist und $u \not \leftrightsquigarrow v$ wenn $i\ne j$.

Was heißt es nun, Zusammenhangskomponenten zu berechnen?

Problem (Zusammenhangskomponenten berechnen). Sei $G=(V,E)$ ein Graph, gegeben zum Beispiel als unsortierte Liste seiner Kanten. Wir nehmen an, dass $V = \{1, \dots, n\}$ gilt. Wir wollen an Array $[c_1, c_2, \dots, c_n]$ berechnen, so dass $c_i$ der "Name" der Zusammenhangskomponente vom Knoten $i$. Dass also gilt:

\begin{align*} c_i = c_j \Longleftrightarrow i \leftrightsquigarrow j \end{align*}

Fragment Merging

Wir stellen nun den Algorithmus Fragment Merging. Die Idee ist, dass wir die Knotenmenge in Fragmente partitioniert haben und in jeder Phase mehrere Fragmente, die mit Kanten verbunden sind, zu einem großen Fragment verschmelzen. Der Algorithmus endet, wenn keine zwei Fragmente durch Kanten verbunden sind; dann sind die Fragmente genau die Zusammenhangskomponenten.

Definition Sei $G = (V,E$ ein Graph. Eine Fragmentfärbung ist eine Funktion $f: V \rightarrow X$ in eine beliebige Farbmenge $X$, so dass

\begin{align*} \forall u, v \in V: \ f(u) = f(v) \rightarrow (u \leftrightsquigarrow v) \ . \end{align*}

In Worten: wenn $u$ und $v$ die gleiche Farbe haben, dann gibt es einen Pfad von $u$ nach $v$. Für eine Farbe $c \in X$ nennen wir

\begin{align*} V_c := \{u \in V \ | \ f(u) = c\} \end{align*}

die Farbklasse $c$.

Es gibt zwei extreme Beispiele für Fragmentfärbungen:

  1. Seien $C_1, \dots, C_k$ die Zusammenhangskomponenten von $G$. Wenn wir $f(u)$ definieren als dasjenige $i$ mit $u \in C_i$, dann ist $f$ eine Fragmentfärbung.
  2. Die "triviale" Färbung $f(u) := u$ ist auch eine Fragmentfärbung.

Beachten Sie: wenn es $k$ Zusammenhangskomponenten gibt, dann muss jede Fragmentfärbung mindestens $k$ Farben verwenden; sie Farbklassen entsprechen den Zusammenhangskomponenten genau dann, wenn genau $k$ Farben verwendet werden.

Der Algorithmus. Wir ersetzen jede ungerichtete Kanten $\{u,v\}$ durch zwei gerichtete $(u,v)$, $(v,u)$.

  1. Jeder Knoten $u$ hat eine "Farbe" $f(u)$; es gilt zu jedem Zeitpunkt: wenn $f(u) = f(v)$, dann gibt es einen Pfad von $u$ nach $v$. Für eine Farbe $c$ sei $V_c := \{u \in V \ | \ f(u) = c\}$; wir nennen $V_c$ ein Fragment.
  2. Pro Phase reicht jede Kante $(u,v)$ einen "Umfärbe-Vorschlag" $(f(u), f(v))$ ein, falls $f(u) \ne f(v)$ ist. Die Interpretation ist: die Kante $(u,v)$ schlägt vor, alle Knoten mit Farbe $f(u)$ umzufärben in Farbe $f(v)$. Nun soll pro Farbklasse der kleinste Vorschlag gewinnen:
    Im obigen Beispiel reicht Kante $(u,v)$ den Vorschlag Farbe 2 soll durch 8 ersetzt werden ein; dieser Vorschlag gewinnt jedoch nicht, weil er durch Farbe 2 soll durch 3 ersetzt werden ausgestochen wird. Wie implementieren wir diese Minimum-Operation?
  3. Jede Kante $(u,v)$ erstellt einen Vorschlag und schreibt diesen in eine dezidierte Zelle. Falls jedoch $f(u) = f(v)$ ist, so wird kein Vorschlag eingereicht. Im obigen Beispiel erhalten wir die Vorschläge

    [(7,8), (7,8), (8,7), (8,7), (8,9), (8,2), (2,8), (2,3), (3,2), (3,6), (3,6), (6,3), (6,5), (6,3), (6,4), (5,6), (5,6), (4,8), (4,6)]

    Wir sortieren die Umfärbe-Vorschläge $(c_1, c_2)$ lexikographisch:

    [(2, 3), (2, 8), (3, 2), (3, 6), (3, 6), (4, 6), (4, 8), (5, 6), (5, 6), (6, 3), (6, 3), (6, 4), (6, 5), (7, 8), (7, 8), (8, 2), (8, 7), (8, 7), (8, 9)]

    Um nun pro Fragment das Minimum zu bestimmen, betrachtet jeder Prozessor "seine" Zelle im Array und die links davon. So kann er feststellen, ob "seine" Zelle den Beginn eines Fragments markiert. Falls nicht, so wird der Vorschlag gestrichen:

    [(2, 3), (2, 8), (3, 2), 3, 6), 3, 6), (4, 6), 4, 8), (5, 6), 5, 6), (6, 3), 6, 3), 6, 4), 6, 5), (7, 8), 7, 8), (8, 2), 8, 7), 8, 7), 8, 9)]

    Es bleiben also folgende Vorschläge übrig:

    [(2, 3), (3, 2), (4, 6), (5, 6), (6, 3), (7, 8), (8, 2)]

    Die Menge der Paare bildet eine binäre Relation $P$ auf der Menge der unvollständigen Farbklassen; in der Tat gibt es für eine unvollständige Farbklasse $c$ genau ein $c'$ mit $(c,c') \in P$. Die Relation $P$ ist also eine Funktion, und wir schreiben $c' = P(c)$ für dieses eindeutige $c'$. Die Funktion $P$ lässt sich graphisch als gerichteter Graph darstellen:

  4. Diese Vorschläge definieren ihrerseits einen gerichteten Graphen $H$ auf den Fragmenten. Vollständige Fragmente, also solche, die bereits eine ganze Zusammenhangskomponente sind, sind in $H$ isolierte Knoten. Andere, nicht vollständige Fragmente, haben genau eine ausgehende Kante. Für ein Fragment $c$ bezeichne $p(c)$ den Zielknoten dieser ausgehenden Kante. Wie kann nun dieser Graph aussehen?
  5. Generell: wenn Sie eine Funktion $p: X \rightarrow X$ und den gerichteten Graphen $H = (X, \{(u, p(u)) \ | \ u \in X\})$ betrachten, so hat $H$ eine sehr spezielle Struktur: eine Menge gerichteter Zyklen und eine Menge von Bäumen, die an den Zyklen-Knoten hängen. In unserem Falle ist die Struktur noch spezifischer: jeder solche Zyklus hat Länge 2. Länge $1$ ist nicht möglich, weil dann ja $p(c) = c$, was nicht geht, weil ein Vorschlag $(c, c)$ gar nicht eingereicht worden wäre. Dass Zyklen der Größe 3 oder mehr nicht existieren, ist nicht so offensichtlich.

    Um zu sehen, dass dies gilt, sei $Z$ ein Zyklus aus mindestens drei Farbklassen und sei $c$ die kleinste auf diesem Zyklus. Sei $c' = p(c)$ und $c'' = p(c')$. Woher kommt nun der "Vorschlag" $(c,c')$? Dieser kommt ja von einer Kante $(u,v)$ mit $f(u) = c$ und $f(v) = c'$. Da unser Graph jedoch ungerichtet ist, gibt es auch $(v,u)$, welche den Vorschlag $(c', c)$ einreicht. Für $c'$ gewinnt also ein Vorschlag, der höchstens $c$ ist, und somit gilt $p(c') \leq c$. Laut Annahme unseres Zykels ist jedoch $p(c') = c'' \gt c$.

    Wir schließen: der Graph $H$ besteht aus Zweierzyklen, an denen zum Zyklus gerichtete Bäume hängen.

  6. Jeder Pseudo-Baum hat also genau zwei Wurzeln. Jeder Knoten $c$ kann parallel in einem Schritt feststellen, ob er eine Wurzel ist (falls $p(p(c))=c$), und falls ja, ob er von den beiden Wurzeln der kleinere ist $c \lt p(c)$ . Falls ja, setzt er $p(c) = c$. Jetzt haben wir also eine Menge von zur Wurzel gerichteten Bäumen mit Selbstschleife an der Wurzel.
  7. Jetzt betreiben wir $\log n$ Runden von Pointer Jumping: jede Farbklasse $c$ setzt also $p(c) := p(p(c))$. Nach $\log n$ solchen Jumping-Schritten deutet $p(c)$ auf die Wurzel. Jeder Baum ist nun also zu einem Stern (mit Selbstschleife an der Wurzel) geworden.
  8. Jetzt färben wir um: $f(u) := f(p(u))$.
  9. Wieviele Phasen brauchen wir? Jedes unvollständige Fragment ist Teil eines Baumes von mindestens 2 Knoten. Jeder Baum wird nach Umfärben zu einem Fragment. Die Anzahl der unvollständigen Fragmente halbiert also mindestens.

Laufzeit $O(\log^2 n)$.

Randomisierte Variante

Auf einer CRCW-PRAM mit Arbitrary-Rule (d.h. bei Schreibkonflikten gewinnt ein beliebiger Prozessor), kann die Kante $(u,v)$ ihren Vorschlag $(f(u), f(v))$ direkt in die Speicherzelle $p[f(v)]$ Schreiben. Für jedes unvollständige Fragment $c$ gibt es nun also einen Wert $p[c]$. Dies definiert wiederum einen gerichteten Graphen mit Raus-Grad höchstens $1$. Dieser kann nun aber lange Zyklen haben, und das Tie-Breaking zwischen den beiden Wurzeln geht nicht mehr. Irgendeine Lösung, in der sich manche Knoten selbst zu Wurzeln erklären, geht zwar irgendwie, aber das Pointer Jumping würde immer noch $\log n$ Schritte pro Phase benötigen.

Wir gehen einen anderen Schritt: jede Farbklasse $c$ wählt ein Bit $b_c$. Kanten $(c,c')$ werden nur behalten, wenn $b_c = 1$ und $b_{c'} = 0$ ist; alle anderen werden gelöscht. Der verbleibende Digraph besteht nun aus isolierten Knoten und Sternen. Jede Kante überlebt mit Wahrscheinlichkeit $1/4$ und somit verschwindet jede unvollständige Farbklasse mit Wahrscheinlichkeit $1/4$. Somit nimmt die Anzahl der unvollständigen Fragmente im Erwartungswert um einen Faktor von $3/4$ ab. Vor Phase 1 ist die Anzahl unvollständiger Fragmente höchstens $n$. Nach $t$ Phasen ist sie im Erwartungswert höchstens

\begin{align*} \left(\frac{3}{4}\right)^t \cdot n \ . \end{align*}

Nach $2 \cdot \log_{4/3} n$ Phasen ist sie höchstens $\frac{1}{n^2} \cdot n = \frac{1}{n}$.

Spannbäume

Sei $G = (V,E)$ ein Graph. Ein Spannbaum ist ein Subgraph $(V,F)$ der alle Knoten von $G$ enthält und ein Baum ist, also azyklisch und zusammenhängend. Das geht natürlich nur, wenn $G$ zusammenhängend ist. Andernfalls interessieren wir uns für einen maximalen Wald $(V,F)$, also einen azyklischen Subgraphen, der maximal in dem Sinne ist, dass jede weiter Kante $e \in E \setminus F$ einen Zyklus erzeugen würde: dass also $(V, F')$ azyklisch ist für jedes $F \subsetneq F' \subseteq E$. Es ist nicht schwer, zu sehen, dass ein Wald genau dann maximal in $G$ ist, wenn er die gleichen Zusammenhangskomponenten hat.

Übungsaufgabe Zeigen Sie, wie man in $O(\log^2 n)$ Zeit einen maximalen Wald berechnen kann. Konkret: Sie wollen jede Kante mit $0$ oder $1$ markieren, so dass die mit $1$ markierten Kanten einen maximalen Wald bilden.

Übungsaufgabe Zeigen Sie, wie man in $O(\log^2 n)$ Zeit entscheiden kann, ob ein Graph $G = (V,E)$ bipartit ist!

Tip

Ein Graph ist bipartit genau dann, wenn er zweifärbbar ist. Wenn ich Ihnen einen Spannbaum $(V,F)$ von $G= (V,E$) gebe, können Sie dann schnell entscheiden, ob $G$ zweifärbbar ist? Der Baum $(V,F)$ ist natürlich in jedem Falle zweifärbbar...