Beispiellösung zu den ¨Ubungen Datenstrukturen und Algorithmen

Werbung
Robert Elsässer
u.v.a.
Paderborn, den 25. Juni 2009
Beispiellösung zu den Übungen
Datenstrukturen und Algorithmen
SS 2009
Blatt 10
AUFGABE 1:
Zunächst einmal kann festgestellt werden, dass sich die Laufzeitschranke auch wie folgt ausdrücken lässt: O(|V | · |V | + |E|2 ) = O(|E| · (|V | + |E|)). Um zu überprüfen ob ein ungerichteter Graph G = (V, E) eine Brückenkante enthält, müssen wir für jede Kante aus e ∈ E
überprüfen, ob der Graph G0 = (V, E \ {e}) noch zusammenhängend ist. Ist G0 nicht mehr
zusammenhängend, war e eine Brückenkante. Der Algorithmus HasBride(G) bekommt als
Eingabe einen ungerichteten Graphen G und liefert false zurück, falls G keine Brückenkante
hat, sonst true.
1 for each e ∈ E do
2
G0 = (V, E \ {e})
3
BF S(G0 , v ∈ V )
4
if G0 nicht mehr zusammenhängend
5
then return true
6 else return false
Zur Laufzeit: Die For-Schleife wird höchstens |E| mal durchlaufen. In jeder Iteration wird
eine Breitensuche auf einem Teilgraphen G0 von G ausgeführt mit einer bekannten Laufzeit
von O(|V | + |E|). Die Zeilen (4)-(6) können in konstanter Zeit erledigt werden. Insgesamt
ergibt sich also folgende Laufzeit für HasBride(G): O(|E| · (|V | + |E|)) = O(|V | · |V | + |E|2 ).
Zur Korrektheit: Fallunterscheidung
• Sei G = (V, E) ein ungerichteter Graph mit einer Brückenkante a ∈ E.
a wird in einer Iteration der for-Schleife aus G entfernt, d.h. der Graph G0a hat mindestens zwei Zusammenhangskomponenten. Die Breitensuche auf G0a liefert, dass G0a nicht
zusammenhängend ist. HasBride(G) liefert true zurück, was korrekt ist.
• Sei G = (V, E) ein ungerichteter Graph ohne Brückenkante.
Graph G0a besteht für alle a ∈ E immer aus genau einer Zusammenhangskomponente,
was durch die Breitensuche überprüft wird. HasBride(G) liefert false zurück, was
korrekt ist.
AUFGABE 2:
a) Die zu G zugehörige Adjazenzmatrix sieht wie folgt aus:
Der Graph sieht wie folgt aus:
Tabelle 1: Adjazenzmatrix zum Graphen G
s a b c d e f
s
10 5
5
a
2 1
b
3
5
5 6
c
3
5 2
d
1 1
e
1
1
f 2
4
Abbildung 1: Gerichteter, gewichteter Graph G = (V, E)
V \S
d[v]
a
10
V \S
d[v]
b c
d
5 ∞ ∞
a c
d
e
8 10 ∞ ∞
V \S
d[v]
V \S
d[v]
V \S
d[v]
e f
S = {s}, δ(s, s) = 0
∞ 5
f
S = {s, b}, δ(s, b) = 5
5
a c d e
S = {s, b, f }, δ(s, f ) = 5
8 10 ∞ 9
c d
10 ∞
e
S = {s, b, f, a}, δ(s, a) = 8
9
c d
S = {s, b, f, a, e}, δ(s, e) = 9
10 ∞
V \S
d[v]
d
S = {s, b, f, a, e, c}, δ(s, c) = 10
15
S = {s, b, f, a, e, c, d}, δ(s, d) = 15
b)
c) Um das Problem Single Source Shortest Path in Zeit O(|V | + |E|) für einen gerichteten,
gewichteten Graphen zu lösen, wobei alle Kanten e ∈ E das Gewicht 1 haben, kann
die Breitensuche angewendet werden. Input: Ein gewichteter, ungerichteter Graph und
∀e ∈ E: gewicht(e) = 1 und einen Startknoten s ∈ V . Output: Der kürzeste Weg von
s zu allen anderen Knoten v ∈ V .
Ausgehend von einem Startknoten s werden in der Breitensuche zunächst alle, zu s adjazenten Knoten, entdeckt, wobei jeder dieser adjazenten Knoten die Distanz 1 hat. Zu
diesen Knoten wurde also bereits ein kürzester Weg gefunden. Anschließend werden die
Nachbarn, der Knoten mit Distanz 1, entdeckt. Zu diesen wurde ebenfalls ein kürzester
Weg gefunden, denn diese Knoten sind nicht adjazent zu s und die Distanz zu s ist mit
2 minimal für einen nicht-adjazenten Knoten. So werden im Laufe der Ausführung der
Breitensuche zu allen verbleibenden Knoten v ∈ V kürzeste Wege gefunden.
Die Laufzeit der Breitensuche ist mit O(|V | + |E|) bekannt und somit können in einem
gerichteten, gewichteten Graphen mit Kanten, deren Gewicht genau 1 ist, kürzeste
Wege in Zeit O(|V | + |E|) berechnet werden.
AUFGABE 3:
Grundsätzlich gibt es zwei Möglichkeiten die Aufgabe zu lösen. Es kann entweder ein Algorithmus entworfen werden, der über alle Knoten v ∈ V iteriert und überprüft ob für jeden Knoten
gilt: Eingangsgrad(v) =Ausgangsgrad(v). Bei diesem Algorithmus sollte allerdings zur Korrektheit bewiesen werden, dass in einem gerichteten, stark zusammenhängenden Graphen genau dann ein Eulerkreis existiert, wenn für alle Knoten Eingangsgrad(v) =Ausgangsgrad(v).
Alternativ kann ein Algorithmus entworfen werden, der den Graphen traversiert und nach
einfachen (kantendisjunkten) Kreisen sucht, also Kreisen im Graphen G, die keine gemeinsamen Kanten haben.
1) Input: G = (V, E) ein endlicher, gerichteter Graph.
Output: GraphContainsEulerCircle“, wenn G einen Eulerkreis enthält, GraphContains”
”
NoEulerCircle“ sonst.
1 Strongly − Connected − Components(G)
2 if G consists of more than one strongly connected component
3 then return GraphContainsN oEulerCircle“
”
4 else
5
for for each v ∈ V do
6
if Indegree(v) ! = Outdegree(v)
7
then return GraphContainsN oEulerCircle“
”
8
else
9
return GraphContainsEulerCircle“
”
Zur Korrektheit: In einem endlichen, gerichteten, stark zusammenhängenden Graphen G =
(V, E) existiert genau dann ein Eulerkreis, wenn für alle v ∈ V gilt: Eingangsgrad(v) =Ausgangsgrad(v).
Proof: ⇒“ Wir nennen einen Kreis in G einfach, wenn beim Durchlaufen des Kreies jeder
”
Knoten nur einmal besucht wird. Wir nennen einen Kreis komplex, wenn ein Knoten beim
Durchlauf des Kreises mehrfach besucht wird. In einem einfachen Kreis C gilt für jeden
Knoten v ∈ C, dass Eingangsgrad(v)=Ausgangsgrad(v) = 1. Jeder komplexe Kreis kann als
Vereinigung von einfachen Kreisen ausgedrückt werden. Das impliziert, dass jeder Knoten in
einem komplexen Kreis (insbesondere in einem Eulerkreis) einen Eingangsgrad haben muss,
der gleich dem Ausgangsgrad ist. Wenn ein Graph also einen Eulerkreis hat, so muss jeder
Knoten gleichen Ein- und Ausgangsgrad haben.
Proof: ⇐“ Angenommen wir haben einen zusammenhängenden Graphen G = (V, E) und
”
für alle v ∈ V gilt Ausgangsgrad(v) =Eingangsgrad(v). Es sei weiterhin K der längste komplexe Kreis in G. Wenn K kein Eulerkreis ist, dann gibt es einen Knoten v ∈ G, der in K
enthalten ist, aber noch Kanten hat, die nicht zu K gehören. Wir konstruieren nun einen
Kreis K 0 in G − K, der mit v beginnt und sich wieder schließt, indem wir G − K traversieren.
Da der Graph stark zusammenhängend ist und für alle Knoten, deren Kanten noch nicht zu
K gehören gilt, dass Ausgangsgrad=Eingangsgrad, muss es so einen Kreis geben. Somit gibt
es aber einen noch größeren komplexen Kreis K 00 der aus der Vereinigung von K und K 0
konstruiert werden kann. Dies widerspricht der Voraussetzung, dass K der längste komplexe
Kreis in G ist und somit muss K ein Eulerkreis sein.
In den Zeilen (1)-(3) prüft der Algorithmus, ob der Graph aus mehreren starken Zusammenhangskomponenten besteht. Sollte dies der Fall sein (gilt insbeondere für Knoten, die
Ausgangsgrad=Eingangsgrad=0 haben) so gibt der Algorithmus korrekter Weise GraphCon”
tainsNoEulerCircle“ zurück. Andernfalls wird ab Zeile (4) für jeden Knoten v ∈ V geprüft,
ob gilt: Eingangsgrad(v) =Ausgangsgrad(v). Gilt dies für einen Knoten nicht, so kann G keinen Eulerkreis enthalten und der Algorithmus liefert GraphContainsNoEulerCircle“ zurück.
”
Andernfalls gilt die Eigenschaft für alle Kanten und der Algorithmus liefert GraphContain”
sEulerCircle“ zurück. Wenn man den Pfad des Eulerkreises überdies Ausgeben möchte, muss
man sukzessive einfache Kreise in G entdecken und diese an Kreuzenden Knoten miteinander
zu einem maximal großen, komplexen Kreis zusammenführen. Hat man alle einfachen Kreise
entdeckt und zu einem komplexen Kreis ergänzt, kann man den Pfad dieses komplexen Kreises ablaufen und ausgeben. Dieser Kreis muss, wie schon gezeigt wurde, ein Eulerkreis sein.
Zur Laufzeit: Starke Zusammenhangskomponenten können mittels einer modifizierten Tiefensuche in Zeit O(|V | + |E|) berechnet werden (siehe PÜ 10). Die Überprüfung aller Kanten
auf die Gleichheit von Ein- und Ausgangsgrad kann mit O(|E|) abgeschätzt werden. Sollte
man darüber hinaus auch noch den Pfad berechnen wollen, iteriert man bei der Suche nach
einfachen Kreisen genau einmal über alle Knoten und ihre adjazenten Kanten. Somit kann
die Pfadausgabe mit O(|V | + |E|) abgeschätzt werden. Insgesamt ergibt sich eine Laufzeit
von O(2 · |V | + 3 · |E|) was asymptotisch nicht schlechter ist als O(|V | + |E|).
AUFGABE 4:
Zu dieser Programmieraufgabe gibt es keine Musterlösung.
Herunterladen