Robert Elsässer u.v.a. Paderborn, den 9. Juli 2008 Beispiellösung zu den Übungen Datenstrukturen und Algorithmen SS 2009 Blatt 11 AUFGABE 1: a) G=(V,E) Partitionize(G,k) 1 2 3 4 5 6 7 8 9 10 11 12 i f k ≥ |V | t h e n r e t u r n true f o r e a c h k− P a r t i t i o n P o f V do p a r t i t i o n F o u n d ← true f o r e a c h W ∈ P do f o r e a c h v ∈ W do f o r e a c h ( v , u ) ∈ E do i f u ∈ W then partitionFound ← false i f p a r t i t i o n F o u n d = true then r e t u r n true return false Laufzeitanalyse Die k-Partition besteht immer aus k Elementen. Betrachte diese k Elemente als geordnetes Tupel P = (V1 , V2 , ..., Vk ). Im Laufe des Algorithmus nimmt (im worst-case) jedes dieser Elemente Vi jede mögliche Teilmenge von V an. Es handelt sich also um die Potenzmenge von V, welche Kardinalität O(2|V | ) besitzt. Eine obere Schranke für die möglichen Ausprägungen von P ergibt sich aus dem Kreuzprok dukt K = V1 × V2 × . . . × Vk . Folglich hat K Kardinalität O(2|V | ) = O(2|V |·k ). Dies sind genau die Schleifendurchläufe von Zeile 3. S Da kj=1 Vj = V , besitzen Zeile 4 und 5 zusammen Laufzeit O(|V |), denn es wird jeder Knoten aus V genau ein mal durchlaufen. Die Laufzeit von Zeile 7 lässt sich zudem durch O(|V |) abschätzen, da v höchstens |V | − 1 Nachbarknoten besitzen kann. |·k |V | · |V | ) = O(2|V |·k · |V |2 ). Wegen Zusammengefasst ergibt sich Laufzeit O(2| |V {z } · |{z} |{z} Zeile3 Zeile4,5 Zeile7 Zeile 1 und 2 gilt außerdem ab Zeile 3, dass k ≤ |V |. Folglich lässt sich die Laufzeit auch 2 durch O(2|V | · |V |2 ) angeben. Korrektheit Zunächst gilt es festzustellen, dass ein Graph mit weniger oder gleich k Knoten immer kpartit ist, wenn jede Menge der Partition maximal einen Knoten enthält und verbleibende Mengen leer sind. Wenn ein Graph G =(V,E) k-partit ist, dann muss es in der Menge aller k-Partitionen eine k-Partition (V1 , . . . , Vk ) geben, wobei jede Kante ausschließlich zwischen zwei Knoten aus verschiedenen Vi , Vj verlaufen darf. Diese Eigenschaft wird in den Zeilen 4-7 überprüft. Für jeden Knoten wird überprüft, ob alle adjazenten Knoten in einer anderen Partition sind. Ist dies für alle Knoten der Partition gegeben, wurde somit eine k-Partition gefunden. Andernfalls gibt der Algorithmus nach Überprüfung aller Partitionen false zurück. b) G=(V,E) M INIMUM K(G) 1 2 3 f o r k ← 1 t o |V | i f P a r t i t i o n i z e (G, k ) = t r u e t h e n return k Laufzeitanalyse 2 Partitionize(G,k) hat nach Aufgabenteil a) Laufzeit O(2|V | · |V |2 ). Die Schleife aus Zeile 1 2 wird im worst-case |V | mal durchlaufen. Der Algorithmus hat also Laufzeit O(2|V | · |V |3 ) Rückgabe Für k = |V | liegt jeder Knoten in einer eigenen Partition. Folglich kann es keinen Knoten in einer Partition geben, der eine Kante zu einem Knoten in der selben Partition besitzt. Damit liefert der Algorithmus Partitionize(G,k) für k = |V | stets true zurück. Der Algorithmus MinimumK(G) hat also stets eine Ausgabe. AUFGABE 2: Initialisierung: A = {}, Union-Find-Datenstruktur: {A}, {B}, {C}, {D}, {E}, {F }, {G}, {H}, {I} • Kante: (A, E), A = {(A, E)}, Union-Find-Datenstruktur: {A, E}, {B}, {C}, {D}, {F }, {G}, {H}, {I} • Kante: (F, G), A = {(A, E), (F, G)}, Union-Find-Datenstruktur: {A, E}, {B}, {C}, {D}, {F, G}, {H}, {I} • Kante: (D, I), A = {(A, E), (F, G), (D, I)}, Union-Find-Datenstruktur: {A, E}, {B}, {C}, {D, I}, {F, G}, {H} • Kante: (G, H), A = {(A, E), (F, G), (D, I), (G, H)}, Union-Find-Datenstruktur: {A, E}, {B}, {C}, {D, I}, {F, G, H} • Kante: (A, B), A = {(A, E), (F, G), (D, I), (G, H), (A, B)}, Union-Find-Datenstruktur: {A, B, E}, {C}, {D, I}, {F, G, H} • Kante: (C, D), A = {(A, E), (F, G), (D, I), (G, H), (A, B), (C, D)}, Union-Find-Datenstruktur: {A, B, E}, {C, D, I}, {F, G, H} • Kante: (B, I), A = {(A, E), (F, G), (D, I), (G, H), (A, B), (C, D), (B, I)}, Union-Find-Datenstruktur: {A, B, C, D, E, I}, {F, G, H} • Kante: (D, G), A = {(A, E), (F, G), (D, I), (G, H), (A, B), (C, D), (B, I), (D, G)}, Union-Find-Datenstruktur: {A, B, C, D, E, F, G, H, I} AUFGABE 3: Zur Eindeutigkeit des Spannbaums: Annahme: Es existieren zwei verschiedene minimale Spannbäume S1 = (V, E1 ) und S2 = (V, E2 ). Da die Spannbäume verschieden sind, ist E1 ∆E2 6= ∅1 . Wähle e∗ ∈ E1 ∆E2 und gelte o.B.d.A. e∗ ∈ E1 (es ist also e∗ ∈ / E2 !). Definiere Sdivided := (V, E1 \ {e∗ }). Offensichtlich sind durch das Entfernen der Kante zwei Teilbäume entstanden, seien dies T1 := (VT 1 , ET 1 ) und T2 := (VT 2 , ET 2 ), wobei VT 1 ∪ VT 2 = V und ET 1 ∪ ET 2 = E1 \ {e∗ }. Da S2 ein Spannbaum und da S2 zusammenhängend ist, muss es eine Kante c ∈ VT 1 × VT 2 (bzw. VT 1 × VT 2 ∪ VT 2 × VT 1 ; der Graph ist aber ohnehin ungerichtet) geben, die ein Element der Kantenmenge E2 ist (daraus folgt c 6= e∗ ). Durch die Wahl von c und e∗ gilt wegen der paarweise verschiedenen Kantengewichte w(c) 6= w(e∗ ). Betrachte nun folgende Fälle: Fall 1 (w(c) < w(e∗ )): Definiere den Graph Scombined := (V, (E1 \ {e∗ }) ∪ {c}). Der Graph ist wieder ein Spannbaum, da er die Knotenmengen VT 1 und VT 2 verbindet. Es gilt für das Gewicht des Graphen Scombined : w(Scombined ) = w(E1 ) − w(e∗ ) + w(c) < w(E1 ) Dies ist ein Widerspruch zur Minimalität von E1 . Fall 2 (w(c) > w(e∗ )): Definiere den Graphen Scombined2 := (V, (E2 \ {c}) ∪ {e∗ }). Der Graph ist wieder ein Spannbaum, da er die Knotenmengen VT 1 und VT 2 verbindet. Dann gilt für das Gewicht des Graphen Scombined2 : w(Scombined2 ) = w(E2 ) − w(c) + w(e∗ ) < w(E2 ) Dies ist ein Widerspruch zur Minimalität von E2 . Also kann es nicht zwei verschiedene minimale Spannbäume geben. Ein Beispiel, bei dem der zweitkleinste minimale Spannbaum nicht eindeutig ist: Der zweitbeste minimale Spannbaum muss mindestens eine Kante, die im minimalen Spannbaum enthalten ist, nicht besitzen. Entfernt man also eine Kante im minimalen Spannbaum aus dem Graphen, und benutzt den Algorithmus von Kruskal oder Prim, so erhält man (genau) einen Kandidaten für einen zweitbesten minimalen Spannbaum (sofern man keine Brückenkante entfernt hat). Das führt man dies nacheinander für alle Kanten durch, so erhält man |V | Spannbäume, von denen diejenigen mit kleinstem Gewicht die zweitbesten sind. Zu Beachten ist, dass, wenn an eine Kante e mit Gewicht w(e) entfernt, mindestens eine weitere Kante e0 mit Gewicht w(e0 ) hinzugefügt werden muss. Der so erhaltene Spannbaum ist um w(e0 ) − w(e) schwerer als der minimale. Um ein Beispiel für einen Graphen mit mehreren zweitkleinsten minimalen Spannbäumen zu konstruieren, wählt man also eine Graphen, der a) möglichst einfach ist, so dass klar ist, welche Kanten man hinzunehmen muss, wenn eine weggenommen wird b) zwei Kantenpaare besitzt, bei denen die Differenz gleich einer konstanten p ist. Betrachte den folgenden Graphen: 1 ∆ bezeichnet die symmetrische Differenz zweier Mengen A und B: A∆B := (A ∪ B) \ (A ∩ B). Die symmetrische Differenz zweier Mengen enthält also genau diejenigen Elemente, die in exakt einer Menge enthalten sind. Der Graph hat folgenden minimalen Spannbaum mit Gewicht 20: Er hat aber zwei zweitbeste minimale Spannbäume mit Gewicht 36: AUFGABE 4: a) Knoten u,v in gleicher Zusammenhangskomponente ⇒ u,v in der gleichen Menge: Da u, v in der gleichen Zusammenhangskomponente sind, existieren einfache Wege u ! v. Für jede Kante (u0 , v 0 ) auf diesen Wegen vereinigt der Algorithmus die Mengen, in der die Knoten u0 , v 0 sind. Somit sind nach Abarbeitung aller Kanten u und v in der gleichen Menge. Knoten u,v in gleicher Zusammenhangskomponente ⇐ u,v in der gleichen Menge: Betrachte die Invariante: Vor jedem Schleifendurchlauf in Zeile 3 gilt, dass für alle Knoten u, v einer Menge Wege u ! v existieren. Initialisierung: Vor dem ersten Durchlauf der Schleife befindet sich in jeder Menge genau ein Knoten, somit gilt die Aussage vor dem ersten Durchlauf der Schleife. Erhaltung: Bei Durchlauf der Schleife mit der Kante (u, v) vereinigt der Algorithmus die Menge, in der u ist, mit der Menge, in der v ist, sofern diese nicht ohnehin gleich sind. Nach der Invarianten existieren in jeder der beiden Mengen Wege zwischen allen Knoten. Weil es die Kante (u, v) gibt, existieren somit auch Wege zwischen allen Knoten der Vereinigungsmenge. Die Invariante gilt weiterhin. Terminierung: Nach Terminierung der Schleife gilt weiterhin die Invariante, woraus die zu zeigende Behauptung direkt folgt. b) Insgesamt wird n = m1 = |V | mal die Operation Make-Set aufgerufen, und genau m2 = 2 · |E| mal die Operation Find-Set sowie höchstens m3 = |V | mal die Operation Union. Nach Satz 15.8 der Vorlesung können die Operationen somit in O(|V |+|E|+|V | log |V |) = O(|E| + |V | log |V |) ausgeführt werden.