Einfacher Algorithmus für topologisches Sortieren 1: 2: 3: 4: 5: 6: 7: 8: 9: {(1) Initialisierung} i := 0 W := V {W – die Menge der noch nicht bearbeiteten Knoten} {(2) Rekursionsschritt} while ein Knoten x ∈ W ohne Vorgänger in W existiert do i := i + 1; ord(x) = i; W := W − {x} end while 1 Algorithmus für Topologisches Sortieren Eingabe: Gerichteter Graph G = (V, E) mit n Knoten und k Kanten Ausgabe: Topologische Sortierung ord : V → {1, . . . , n} von G, falls G azyklisch ist 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: {(1) Initialisierung} i := 0 {i – die letzte Zahl, die ord benutzt hat} U := ∅ {U - die Menge aller Knoten v mit IN [v] = 0} IN [1] := 0, . . . , IN [n] := 0 for alle Knoten v in V do for alle Knoten w mit einer Kante (v, w) in E do IN [w] := IN [w] + 1 end for end for for alle Knoten v in V do if IN [w] = 0 then U := U ∪ {v} end if end for {(2) Rekursionsschritt} while U einen Knoten v enthält do U := U − v i := i + 1 ord(v) := i for alle Knoten w mit (v, w) ∈ E do IN [w] := IN [w] − 1 if IN [w] = 0 then U := U ∪ {w} end if end for end while {(3) Ausgabe} Falls n = i, ist ord eine topologische Sortierung von G. Falls n > i, ist die Ausgabe ein Code dafür, dass G nicht azyklisch ist. 2 Algorithmus für 2-Färbung Eingabe: Ungerichteter Graph G = (V, E) Ausgabe: Eine 2-Färbung V = ROT ∪ BLAU , falls es eine gibt. 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: {1. Initialisierung} ROT := ∅ BLAU := ∅ F := ∅ {Menge der zuletzt gefärbten Knoten} {2. Rekursionsschritt} while V 6= ∅ do wähle v aus V V := V − {v} ROT := ROT ∪ {v} F := F ∪ {v} while F 6= ∅ do wähle w in F for alle Knoten u ∈ V mit (u, w) ∈ E do if w ∈ ROT then BLAU := BLAU ∪ {u} else ROT := ROT ∪ {u} end if F := F ∪ {u} V := V − {u} end for F := F − {w} end while end while {3. Ausgabe} Falls ROT oder BLAU eine Kante aus E enthalten, ist die Ausgabe ein Code dafür, dass G keine 2-Färbung hat. Falls weder ROT noch BLAU eine Kante enthält, ist dies die gesuchte 2-Färbung. 3 Algorithmus für gerichteter Weg Eingabe: Ein gerichteter Graph G = (V, E) und zwei Knoten v und w Augabe: JA, falls ein gerichteter Weg von v nach w führt, ansonsten NEIN 1: {Initialisierung:} 2: M := {v} 3: {Rekursionsschritt:} 4: while eine Kante (x, y) mit x ∈ M und y ∈ / M existiert do 5: M := M ∪ {y} 6: E := E − {(x, y)} 7: end while 8: {Ausgabe:} 9: JA, falls w ∈ M , NEIN falls w 6∈ M . 4 Algorithmus für Starke Komponenten Eingabe: gerichteter Graph G Aufgabe: Starke Kompontenen berechnen 1: K1 := ∅, . . . , Kn := ∅ 2: i := 0 {Komponenten initialisieren} 3: while V 6= ∅ do 4: i := i + 1 5: Wähle v ∈ V 6: for alle Knoten w ∈ V do 7: if es existieren gerichtete Wege v → · · · → w und w → · · · → v then 8: Ki := Ki ∪ { w } 9: V := V \ { w } 10: end if 11: end for 12: end while 5 Simulation einer 2-Band-TM durch eine 4-Spur-TM Gegeben: 2-Band TM M = (Q, Σ, δ, q0 , qf ) Konstruiere: 4-Spur TM M̄ mit • Zusatzspeicher (s1 , s2 , x) • Bandalphabet Γ = Σ̄ × { ⇑, # } × Σ̄ × { ⇑, # } \ { (#, #, #, #) } Simulation: 1. Anfang: ··· ··· ··· ··· # # # # v1 ⇑ # ⇑ v1 # # # ··· ··· ··· ··· vn # # # # # # # ··· ··· ··· ··· 2. Berechnungsschritte: 1: while true do 2: Lese Spur 1 nach s1 3: Gehe zu ⇑ auf Spur 4 (abhängig von x = ` oder x = r) 4: Lese Spur 3 nach s2 5: Berechne Folgezustand aufgrund aktuellem Zustand q von M und (s1 , s2 ) im Speicher 6: Kopfmarker gemäß Verhalten von M auf Spuren 2 & 4 anpassen 7: Falls M hält (bzw. akzeptiert), halten (bzw. akzeptieren) 8: Kopf von M̄ zu ⇑ auf Spur 2 bewegen 9: end while 6 Maximales Matching Grundbegriffe. Es sei G = (S, T, E) ein gegebener bipartiter Graph und M ⊆ E ein Matching von G: • e heißt freie Kante falls e 6∈ M und unfrei falls e ∈ M ; • x ∈ S ∪ T heißt freier Knoten, falls x kein Endknoten einer Kante von M ist; • ein Weg (oder Pfad) p in G heißt erweiternd falls seine Endknoten frei und seine Kanten abwechselnd frei und unfrei sind. Satz 1. Falls ein Matching M einen erweiternden Weg W hat, gibt es ein größeres Matching M 0 , das aus M dadurch ensteht, dass die freien und unfreien Kanten von W ausgetauscht werden. Satz 2. Jedes Matching, für das es keinen erweiternden Weg gibt, ist maximal. Algorithmus (angelehnt an Ford-Fulkerson-Methode für Maxflow) 1: {Initialisierung} 2: Setze K := ∅ 3: Forme aus dem gegebenen bipartiten Graphen G = (S, T, E) den um zwei Knoten erweiterten Graphen G0 = GK ; 4: {Matching Maximieren} 5: while Weg p von s nach t existiert in GK do 6: K := K ∪ { (x, y) | (x, y) ∈ E und (x, y) ∈ p } − { (x, y) | (x, y) ∈ E und (y, x) ∈ p }; 7: GK aktualisieren: die Richtung aller Kanten aus p umdrehen 8: end while 9: gib die Kantenmenge K ∩ E aus 7 Min Vertex Cover Eingabe: Ungerichteter Graph G = (V, E) Aufgabe: finde kleinste Menge D mit D ∪ e 6= ∅ für alle e ∈ E. Bemerkung: das zugrunde liegende E-Problem VC ist NP-vollständig. Approximationsalgorithmus 1: 2: 3: 4: 5: 6: 7: D := ∅ V := die Menge aller Knoten von G E := die Menge aller Kanten von G while E eine Kante (x, y) enthält do D := D ∪ {x, y} E := E − {v : v eine Kante mit Endknoten x oder y} end while 8 SIT(k) (Scheduling of Independent Tasks) Eingabe: Zahlen t1 , . . . , tn . Aufgabe: eine Funktion S : {1, . . . , n} → {1, . . . , k}, für die die Zahl T = max{ X ti , . . . , S(i)=1 X ti } S(i)=k minimal ist. Approximationsalgorithmus für SIT(k) 1: {Tm = die Zeit, die Maschine m bisher gearbeitet hat} 2: sortiere die gegebenen Zeiten, so dass t1 ≥ t2 ≥ · · · ≥ tn 3: for m = 1 to k do 4: Tm := 0 5: end for 6: for i = 1 to n do 7: m := ein Index mit Tm = min{T1 , . . . , Tk } 8: S(i) := m 9: Tm := Tm + ti 10: end for 9 Approximationsschema für SIT(2) Idee: für S = t1 + · · · tn berechne die Mengen B(i) = { b ≤ S | b Summe einer Teilmenge von { t1 , . . . , ti }} 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: {Summe aller ti berechnen} S := t1 + t2 + · · · tn ; {Optimalwert berechnen} B(0) := { 0 }; for i = 2, . . . , n do B(i) := B(i − 1); for j = ti , ti + 1, . . . , S do if j − ti ∈ B(i) then B(i) := B(i) ∪ { j }; end if end for end for T := minimales b ∈ B(n) mit b ≥ S2 ; {Schedule berechnen} b := T ; for i = 1, . . . , n do if b − ti ∈ B(n) then S(i) := 1; b := b − ti ; else S(i) := 2; end if end for 10