• Keine Ergebnisse gefunden

Geschickt Programmieren für den ICPC-WettbewerbFelix Weissenberger Graphenalgorithmen I

N/A
N/A
Protected

Academic year: 2021

Aktie "Geschickt Programmieren für den ICPC-WettbewerbFelix Weissenberger Graphenalgorithmen I"

Copied!
142
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Graphenalgorithmen I

Geschickt Programmieren für den ICPC- Wettbewerb

Felix Weissenberger

(2)

Inhalt

Grundlagen zu Graphen

Begriffe

Darstellung von Graphen

Graphenalgorithmen

Breitensuche

Tiefensuche

Topologisches Sortieren

Zusammenhang - Brücken - Artikulationspunkte

Euler-Touren

(3)

Graph

Ein Graph G = (V, E) besteht aus:

einer Knotenmenge V (vertices)

einer Kantenmenge E (edges)

(4)

Ungerichteter Graph

Kanten repräsentiert durch Teilmengen {u, v} ⊆ V

1 2

4 3

G = (V, E)

V = {1, 2, 3, 4}

E = {{1, 2}, {2, 3}, {2, 4}, {3, 4}}

(5)

Gerichteter Graph

Kanten repräsentiert durch Tupel (u, v) ∈ V x V

1 2

4 3

G = (V, E)

V = {1, 2, 3, 4}

E = {(2, 1), (2, 3), (4, 2), (4, 3)}

(6)

Wege, Pfade, Touren

eine Sequenz v0, e1, v1, ..., en, vn mit vi ∈ V und ei = {vi-1, vi} oder (vi-1, vi) ∈ E heißt Weg

ein Weg mit paarweise verschiedenen Kanten heißt Tour

ein Weg mit paarweise verschiedenen Knoten heißt Pfad

gilt v0 = vn heißen Pfade/Touren geschlossen

(7)

Nachbarschaft, Grad

zwei Knoten, die über eine Kante miteinander verbunden sind heißen Nachbarn

die Anzahl der Nachbarn eines Knoten ist sein Grad

(8)

Zusammenhang

gibt es einen Pfad von u nach v, dann ist v von u aus erreichbar

ein Graph heißt zusammenhängend, wenn jeder Knoten von jedem anderen Knoten erreichbar ist

eine Zusammenhangskomponente ist ein maximal zusammenhängender Teilgraph

(9)

Zusammenhang

1 2

4 3

1 2

4 3

nicht zusammenhängend zusammenhängend

(10)

Zusammenhangs-

komponenten CC´s

1 2

4 3

1 2

4 3

in ungerichteten Graphen

(11)

starke Zusammenhangs- komponenten sCC´s

1 2

4 3

1 2

4 3

in gerichteten Graphen

1 2

4 3

1 2

4 3

(12)

DAG

DAG (directed acyclic graph) ist ein gerichteter azyklischer Graph, d.h. er

enthält keinen gerichteten Kreis (Kreis ist geschlossener Pfad).

(13)

DAG

1 2

4 3

1 2

4 3

1 2

4 3

1 2

4 3

DAG kein DAG

(14)

dünn- und dicht besetzte Graphen

1 2

4 3

1 2

4 3

dünn besetzter Graph

|E|  O(|V|)

dicht besetzter Graph

|E|  O(|V|2)

(15)

Fragen?

(16)

Knoten auf optimalem Pfad

gegeben ist ein ungerichteter,

zusammenhängender Graph und zwei seiner Knoten x und y

gesucht sind alle Knoten, die auf allen

optimalen Pfaden (min. Anz. Kanten) von x nach y liegen

(17)

Knoten auf optimalem

Eingabe:

Pfad

1. Zeile: Anz. Knoten N < 7500, Anz.

Kanten M < 14000, x, y

dann M Zeilen Kanten a b

Ausgabe:

alle gesuchten Knoten (aufsteigend sortiert)

(18)

Darstellung von Graphen

häufige Anforderungen an eine Graph- Datenstruktur:

Kante einfügen/ löschen

Kante finden (Test ob Kante in Graph) Nachbarknoten finden

(19)

Adjazenzmatrix - Konzept

|V| x |V|-Matrix A = (aij) mit aij = 1 falls (i, j) ∈ E, 0 sonst

1 2

4 3

1 2 3 4

1 2 3 4

0 1 0 0

1 0 1 1

0 1 0 1

0 1 1 0

(20)

Adjazenzmatrix - Implementierung

einlesen in Adjazenzmatrix

(21)

Adjazenzmatrix - Analyse

Laufzeiten:

Einfügen/ Löschen O (1)

Finden/ Testen O (1)

Nachbarn finden O (|V|)

Speicher:

O (|V|2) bei

gerichtetem Graph

O (|V|2 / 2) bei

ungerichtetem Graph

(22)

Adjazenzmatrix - Analyse

Verwendung:

bei relativ kleinen Graphen wegen Einfachheit

bei dicht besetzten Graphen

wenn Test ob Kante in Graph effizient implementiert werden soll

(23)

Adjazenzlisten - Konzept

Feld der Länge |V|, das für jeden Knoten eine Liste seiner Nachbarn enthält

1 2

4 3

1 2 3 4

2 3 2 2

4 4 3

(24)

Adjazenzlisten - Implementierung

einlesen in Adjazenzlisten

(25)

Adjazenzlisten - Analyse

Laufzeiten:

Einfügen O (1)

Löschen O (d)

Finden/ Testen O (d)

Nachbarn finden O (1)

mit d max. Grad

Speicher:

O (|V| + |E|) bei gerichtetem Graph

O (|V| + 2|E|) bei ungerichtetem

Graph

(26)

Adjazenzlisten - Analyse

Verwendung:

bei dünn besetzten Graphen

wenn schnell alle Nachbarn eines Knotens gefunden werden müssen

(27)

Inzidenzlisten

jeder Knoten hat eine Liste von Pointern auf seine inzidenten Kanten

Kanteninformation kann leicht modifiziert werden, da für jede Kante nur eine Instanz existiert

(28)

Datenstruktur für Aufgabe

welche Datenstruktur brauchen wir für die Beispielaufgabe?

(29)

Fragen?

(30)

Graphen

„Durchsuchen“

auf systematische Weise den Kanten folgen und die Knoten des Graphen besuchen

Ziel: Eigenschaften über die Struktur des Graphen aufdecken

Breiten- und Tiefensuche sind Grundlage vieler Graphenalgorithmen

(31)

Breitensuche - Konzept

besuche alle Knoten, die den Abstand (Anz.

Kanten) k vom Startknoten haben, bevor

irgendein Knoten mit Abstand k+1 besucht wird

(32)

Breitensuche (BFS) - Implementierung

Eingabegraph G = (V, E) (in Adjazenzlisten- Darstellung) und Startknoten s

zusätzliche Datenstrukturen:

Vorgänger-Feld pred[]

Abstand zum Startknoten d[]

FIFO - Queue Q

(33)

BFS (G,s)

for alle Knoten u ∈ V[G] - {s}

do d[u] ← ∞

pred[u] ← Nil d[s] ← 0

pred[s] ← Nil Q ← ∅

Enqueue(Q, s) while Q ≠ ∅

do u ← Dequeue(Q)

for alle v ∈ Adj[u]

do if d[v] = ∞

then d[v] ← d[u] + 1 pred[v] ← u

Enqueue(Q, v)

a b

d c

0 Nil Nil

Nil Nil

Q a

(34)

BFS (G,s)

for alle Knoten u ∈ V[G] - {s}

do d[u] ← ∞

pred[u] ← Nil d[s] ← 0

pred[s] ← Nil Q ← ∅

Enqueue(Q, s) while Q ≠ ∅

do u ← Dequeue(Q)

for alle v ∈ Adj[u]

do if d[v] = ∞

then d[v] ← d[u] + 1 pred[v] ← u

Enqueue(Q, v)

a b

d c

0 Nil Nil

Nil Nil

Q

(35)

BFS (G,s)

for alle Knoten u ∈ V[G] - {s}

do d[u] ← ∞

pred[u] ← Nil d[s] ← 0

pred[s] ← Nil Q ← ∅

Enqueue(Q, s) while Q ≠ ∅

do u ← Dequeue(Q)

for alle v ∈ Adj[u]

do if d[v] = ∞

then d[v] ← d[u] + 1 pred[v] ← u

Enqueue(Q, v)

a b

d c

0 Nil Nil

Nil Nil

Q

(36)

BFS (G,s)

for alle Knoten u ∈ V[G] - {s}

do d[u] ← ∞

pred[u] ← Nil d[s] ← 0

pred[s] ← Nil Q ← ∅

Enqueue(Q, s) while Q ≠ ∅

do u ← Dequeue(Q)

for alle v ∈ Adj[u]

do if d[v] = ∞

then d[v] ← d[u] + 1 pred[v] ← u

Enqueue(Q, v)

a b

d c

0 Nil 1 a

Nil Nil

Q

(37)

BFS (G,s)

for alle Knoten u ∈ V[G] - {s}

do d[u] ← ∞

pred[u] ← Nil d[s] ← 0

pred[s] ← Nil Q ← ∅

Enqueue(Q, s) while Q ≠ ∅

do u ← Dequeue(Q)

for alle v ∈ Adj[u]

do if d[v] = ∞

then d[v] ← d[u] + 1 pred[v] ← u

Enqueue(Q, v)

a b

d c

0 Nil 1 a

Nil Nil

Q b

(38)

BFS (G,s)

for alle Knoten u ∈ V[G] - {s}

do d[u] ← ∞

pred[u] ← Nil d[s] ← 0

pred[s] ← Nil Q ← ∅

Enqueue(Q, s) while Q ≠ ∅

do u ← Dequeue(Q)

for alle v ∈ Adj[u]

do if d[v] = ∞

then d[v] ← d[u] + 1 pred[v] ← u

Enqueue(Q, v)

a b

d c

0 Nil 1 a

Nil Nil

Q

(39)

BFS (G,s)

for alle Knoten u ∈ V[G] - {s}

do d[u] ← ∞

pred[u] ← Nil d[s] ← 0

pred[s] ← Nil Q ← ∅

Enqueue(Q, s) while Q ≠ ∅

do u ← Dequeue(Q)

for alle v ∈ Adj[u]

do if d[v] = ∞

then d[v] ← d[u] + 1 pred[v] ← u

Enqueue(Q, v)

a b

d c

0 Nil 1 a

Nil Nil

Q

(40)

BFS (G,s)

for alle Knoten u ∈ V[G] - {s}

do d[u] ← ∞

pred[u] ← Nil d[s] ← 0

pred[s] ← Nil Q ← ∅

Enqueue(Q, s) while Q ≠ ∅

do u ← Dequeue(Q)

for alle v ∈ Adj[u]

do if d[v] = ∞

then d[v] ← d[u] + 1 pred[v] ← u

Enqueue(Q, v)

a b

d c

0 Nil 1 a

2 b Nil

Q c

(41)

BFS (G,s)

for alle Knoten u ∈ V[G] - {s}

do d[u] ← ∞

pred[u] ← Nil d[s] ← 0

pred[s] ← Nil Q ← ∅

Enqueue(Q, s) while Q ≠ ∅

do u ← Dequeue(Q)

for alle v ∈ Adj[u]

do if d[v] = ∞

then d[v] ← d[u] + 1 pred[v] ← u

Enqueue(Q, v)

a b

d c

0 Nil 1 a

2 b 2 b

Q d c

(42)

BFS (G,s)

for alle Knoten u ∈ V[G] - {s}

do d[u] ← ∞

pred[u] ← Nil d[s] ← 0

pred[s] ← Nil Q ← ∅

Enqueue(Q, s) while Q ≠ ∅

do u ← Dequeue(Q)

for alle v ∈ Adj[u]

do if d[v] = ∞

then d[v] ← d[u] + 1 pred[v] ← u

Enqueue(Q, v)

a b

d c

0 Nil 1 a

2 b 2 b

Q d

(43)

BFS (G,s)

for alle Knoten u ∈ V[G] - {s}

do d[u] ← ∞

pred[u] ← Nil d[s] ← 0

pred[s] ← Nil Q ← ∅

Enqueue(Q, s) while Q ≠ ∅

do u ← Dequeue(Q)

for alle v ∈ Adj[u]

do if d[v] = ∞

then d[v] ← d[u] + 1 pred[v] ← u

Enqueue(Q, v)

a b

d c

0 Nil 1 a

2 b 2 b

Q

(44)

Breitensuche - Analyse

Laufzeit: O (|V| + |E|)

Ergebnis:

alle vom Startknoten erreichbaren Knoten v d[v] ≠ ∞

Kürzeste Pfade (Anz. Kanten) jedes Knoten v vom Startknoten d[v]

Vorgängerteilgraph über pred[v]

(45)

Tiefensuche - Konzept

gehe so tief einen Pfad in den Graph

hinein, bis es nicht mehr weiter geht, erst dann drehe um

(46)

Tiefensuche (DFS) - Implementierung

Eingabegraph G = (V, E) (in Adjazenzlisten- Darstellung)

zusätzliche Datenstrukturen:

Vorgänger-Feld pred[]

Besucht-Feld visited[]

Entdeckungszeit d[], Endzeit f[]

(47)

DFS(G)

for alle Knoten u ∈ V[G] // Initialisierung do visited[u] ← false

pred[u] ← Nil zeit ← 0

for alle Knoten u ∈ V[G] // für alle unbesuchten do if visited[u] = false // Knoten rufe

then pred[u] ← -1 // DFS-Visit auf DFS-Visit(u)

DFS-Visit(u)

visited[u] ← true d[u] ← time

time ← time + 1

for alle v ∈ Adj[u]

do if not visited[v]

then pred[v] ← u DFS-Visit(v) f[u] ← time

time ← time + 1

(48)

a e f

b c d

Nil

0 -1 Nil Nil

Nil Nil

(49)

a e f

b c d

1 a

0 -1 Nil Nil

Nil Nil

(50)

a e f

b c d

1 a

0 -1 Nil Nil

2 b Nil

(51)

a e f

b c d

1 a

0 -1 Nil Nil

2 b Nil

(52)

a e f

b c d

1 a

0 -1 Nil Nil

2 b 3 c

(53)

a e f

b c d

1 a

0 -1 Nil Nil

2 b 3/4 c

(54)

a e f

b c d

1 a

0 -1 Nil Nil

2/5 b 3/4 c

(55)

a e f

b c d

1 a

0 -1 Nil Nil

2/5 b 3/4 c

(56)

a e f

b c d

1/6 a

0 -1 Nil Nil

2/5 b 3/4 c

(57)

a e f

b c d

1/6 a

0 -1 7 a Nil

2/5 b 3/4 c

(58)

a e f

b c d

1/6 a

0 -1 7 a Nil

2/5 b 3/4 c

(59)

a e f

b c d

1/6 a

0 -1 7/8 a Nil

2/5 b 3/4 c

(60)

a e f

b c d

1/6 a

0/9 -1 7/8 a Nil

2/5 b 3/4 c

(61)

a e f

b c d

1/6 a

0/9 -1 7/8 a 10 -1

2/5 b 3/4 c

(62)

a e f

b c d

1/6 a

0/9 -1 7/8 a 10 -1

2/5 b 3/4 c

(63)

a e f

b c d

1/6 a

0/9 -1 7/8 a 10/11 -1

2/5 b 3/4 c

(64)

Tiefensuche - Analyse

Laufzeit: O(|V| + |E|)

Ergebnis:

Tiefensuchwald pred[]

Wurzel eines Tiefensuchbaums sind Startknoten von DFS-Visit

Entdeckungs- und Endzeiten d[], f[]

Klassifizierung der Kanten

(65)

Tiefensuchwald

a e f

b c d

(66)

Klassifizierung der Kanten

a e f

b c d

Baumkante

Vorwärtskante

Rückwärtskante

Querkante

(67)

Klassifizierung der Kanten

Baum- Vorwärtskante (u, v): d[u] < d[v]

⋀ f[u] > f[v]

Rückwärtskante (u, v): d[u] > d[v] ⋀ f[u] < f[v]

Querkante (u, v): d[u] > d[v] ⋀ f[u] > f[v]

(68)

Topologische Sortierung

eine Topologische Sortierung eines DAG G ist eine lineare Anordnung aller seiner

Knoten mit der Eigenschaft, dass u in der Anordnung vor v liegt, falls es in G eine Kante (u, v) gibt

(69)

Topologisches

Sortieren - Konzept

führe DFS auf G durch und füge Knoten bei ihrer Fertigstellung vorne in eine verkettete Liste ein

(70)

Topologisches Sortieren - Implementierung

Eingabegraph DAG G = (V, E) (in Adjazenzlisten-Darstellung)

Datenstrukturen für DFS

verkettete Liste L

(71)

Topo(G)

for alle Knoten u ∈ V[G]

do visited[u] ← false pred[u] ← Nil

zeit ← 0

for alle Knoten u ∈ V[G]

do if visited[u] = false then pred[u] ← -1

DFS-Visit(u) Topo-Visit(u)

visited[u] ← true d[u] ← time

time ← time + 1

for alle v ∈ Adj[u]

do if not visited[v]

then pred[v] ← u DFS-Visit(v) f[u] ← time

time ← time + 1 Add(L,u)

(72)

Unterhose

Hose

Socken

Schuhe

Unterhose

Socken Hose Schuhe

1 6

2 5 3 4

7 8

(73)

Topologisches

Sortieren - Analyse

Laufzeit: O(|V| + |E|) (DFS)

Ergebnis: topologische Sortierung

Alternativer Algorithmus: Eingangskanten zählen, Knoten mit Eingangsgrad 0

entfernen

(74)

starke Zusammenhangs- komponenten sCC´s

Finde starke Zusammenhangskomponenten in einem gerichteten Graphen

(75)

Erkennung der sCC´s mit Hilfe der Klassifizierung der Kanten also DFS:

Rückwärtskanten erzeugen sCC´s

Problem: Unterscheidung von Rück- und Querkanten

sCC´s - Konzept

(76)

sCC´s - Konzept

finde min. Entdeckungszeit von Knoten u, die von v über eine beliebige Folge von

Baum- und eine Rückwärtskante erreichbar sind:

lowlink von v

(77)

sCC´s Konzept

lowlink[u] = Min von

d[u]

min. d[v] aller Rückwärtskanten (u, v)

min. lowlink[v] aller Baumkanten (u, v)

ist lowlink eines Knotens u gleich seiner

Entdeckungszeit, dann ist u die Wurzel einer Zusammenhangskomponente

(78)

sCC´s -

Implementierung

Stack S zur Unterscheidung von Rückwärts- und Querkanten

Feld zu Speicherung von lowlink von v:

lowlink[v]

Feld zur Speicherung der sCC´s: sCC[]

(79)

Tarjan(G)

for alle Knoten u ∈ V[G] // Inititalisierung do visited[u] ← false

sCC[u] ← u zeit ← 0

for alle Knoten u ∈ V[G]

do if visited[u] = false then Tarjan-Visit(u)

(80)

Tarjan-Visit(u)

visited[u] ← true d[u] ← time

lowlink[u] ← time time ← time + 1

Push(S, u) // aktive Knoten for alle v ∈ Adj[u]

do if not visited[v]

then Tarjan-Visit(v) // Baumkante (u,v)

lowlink[u] ← min(lowlink[u], lowlink[v])

else if inStack(v) //Rückwärts-(Vorwärts)kante then lowlink[u] ← min(lowlink[u], d[v])

if (lowlink[u] = d[u]) // Wurzel einer sCC then sCC[u] ← u)

repeat v ← Pop(S) sCC[v] ← u until (v = u)

(81)

c d e

a b

a

S

0 0

(82)

c d e

a b

b

a

S

0 0

1 1

(83)

c d e

a b

c

b a

S

0 0

2 2

1 1

(84)

c d e

a b

c

b a

S

0 0

2 0

1 1

(85)

c d e

a b

d c b a

S

0 0

2 0 3 3

1 1

(86)

c d e

a b

c

b a

S

0 0

2 0 3 3

1 1

(87)

c d e

a b

0 0

2 0 3 3

1 1

c b a

S

(88)

c d e

a b

0 0

2 0 3 3

1 0

c b a

S

(89)

c d e

a b

0 0

2 0 3 3

1 0

c b a

S

(90)

c d e

a b

S

0 0

2 0 3 3

1 0

(91)

c d e

a b

e

S

0 0

2 0 3 3 4 4

1 0

(92)

c d e

a b

S

0 0

2 0 3 3 4 4

1 0

(93)

sCC´s - Analyse

Laufzeit: O(|V| + |E|) (DFS)

Ergebnis: u, v in einer sCC gdw.

sCC[u] = sCC[v]

altenativer Algorithmus: zweimal BFS mit transponiertem Graph

(94)

Brücken

eine Brücke (kritische Kante) in einem

Graph ist eine Kante, deren Entfernen die Zahl der Zusammenhangskomponenten erhöht

(95)

Brücken - Konzept

führe DFS auf G durch und berechne aktuelle Suchtiefe d[]

min. Suchtiefe von Knoten u, die von v über eine beliebige Folge von Baum- und eine

Rückwärtskante erreichbar sind:

low von v

(96)

Brücken Konzept

eine Baumkante e = (u, v) ist eine Brücke, falls low[v] > d[u]

gibt es keine andere Möglichkeit von u nach v zu gelangen außer e zu benutzen?

ja? e ist Brücke

(97)

u v

low[v] > d[u]

(98)

Bridges(G)

for alle Knoten u ∈ V[G] // Initialisierung do d[u] ← -1

for alle Knoten u ∈ V[G]

do if d[u] = -1

then Bridges-Visit(u, 0, -1) Bridges-Visit(from, cd, parent) low ← d[u]

d[u] ← cd

for alle v ∈ Adj[u] mit v ≠ parent do if d[v] = -1

then i ← Bridges-Visit(v, cd+1, u) if i > cd then Brücke(u,v)

low ← Min(low, i)

else low ← Min(low, d[v]) return low

(99)

a d f

b c e

-1

0 -1 -1

-1 -1

low -1

(100)

a d f

b c e

1

0 -1 -1

-1 -1

low 0

(101)

a d f

b c e

1

0 -1 -1

2 -1

low 1

(102)

a d f

b c e

1

0 -1 -1

2 0 -1

low 0

(103)

a d f

b c e

1 0

0 -1 -1

2 0 -1

low 0

(104)

a d f

b c e

1 0

0 1 -1

2 0 -1

low 0

(105)

a d f

b c e

1 0

0 1 -1

2 0 2

low 1

(106)

a d f

b c e

1 0

0 1 3

2 0 2

low 2

(107)

a d f

b c e

1 0

0 1 3 1

2 0 2

low 1

(108)

a d f

b c e

1 0

0 1 3 1

2 0 2 1

low 1

(109)

a d f

b c e

1 0

0 1 1 3 1

2 0 2 1

low 1

(110)

a d f

b c e

1 0

0 0 1 1 3 1

2 0 2 1

low 0

(111)

Brücken - Analyse

Laufzeit O(|V| + |E|) (DFS)

Ergebnis: alle Brücken des Graphen

(112)

Artikulationspunkte

eine Artikulationspunkt (kritischer Knoten) in einem Graph ist ein Knoten, dessen

Entfernen die Zahl der

Zusammenhangskomponenten erhöht

(113)

Artikulationspunkte - Konzept

führe DFS auf G durch und berechne aktuelle Suchtiefe d[]

min. Suchtiefe von Knoten u, die von v über eine beliebige Folge von Baum- und eine

Rückwärtskante erreichbar sind:

low von v

(114)

Artikulationspunkte (AP) - Konzept

Wurzel eines Tiefensuchbaums ist AP, falls sie mehr als ein Kind hat

jeder andere Knoten u ist AP, falls er ein Kind v hat mit low[v] ≥ d[u]

hat u ein Kind, das mit keinem Knoten, der vor v besucht wurde verbunden ist?

ja? u ist AP

(115)

u

Startknoten

low ≥ d[u]

(116)

APoints(G)

for alle Knoten u ∈ V[G]

do d[u] ← -1

for alle Knoten u ∈ V[G]

do if d[u] = -1

then APoints(u, 0, -1)

APoints-Visit(from, cd, parent) low ← d[u]

d[u] ← cd

children ← 0 ap ← false

for alle v ∈ Adj[u] mit v ≠ parent do if d[v] = -1

then children ← children + 1

i ← APoints-Visit(v, cd+1, u) if i ≥ cd then ap ← true

low ← Min(low, i)

else low ← Min(low, d[v])

if (ap ⋀ cd > 0) ⋁ (cd = 0 ⋀ children > 1) then Artikulationspunkt u

return low

(117)

f

b c e

1 0

0 0 1 1 3 1

2 0 2 1

Wurzel

a b

(118)

Artikulationspunkte - Analyse

Laufzeit O(|V| + |E|)

Ergebnis: alle Artikulationspunkte des Graphen

(119)

Euler-Touren

eine Euler-Tour in einem Graphen, ist eine Tour, die jede Kante besucht

c d

e b

a f

(120)

Euler-Tour

notwendige und hinreichende Bedingungen

geschlossene Euler-Tour:

zusammenhängend und alle Knoten haben gerade Grade

offene Euler-Tour:

zusammenhängend und alle Knoten außer zwei mit ungeradem Grad haben gerade Grade

(121)

Euler-Tour - Konzept

finde eine geschlossene Euler-Tour:

DFS von u bis man über Pfad p wieder zu u gelangt

falls noch unbesuchte Kanten, finde Euler- Tour p´ von u´ (auf p und u´ inzident zu unbesuchter Kante)

füge p´ in p ein

(122)

c d e b

a f

(123)

c d e b

a f

(124)

c d e b

a f

a

(125)

c d e b

a f

a

(126)

c d e b

a f

a

(127)

c d e b

a f

a

(128)

c d

e b

a f

a c

(129)

c d e b

a f

a c

(130)

c d e b

a f

a c

(131)

c d

e

b

a f

a c e

(132)

c d e b

a f

a c e f

(133)

c d

e b

a f

a c e f d

(134)

c d

e

b

a f

a c e f d e

(135)

c d

b e

a f

a c e f d e b

(136)

c d

e b

a f

a c e f d e b d

(137)

c d

e b

a f

a c e f d e b d c

(138)

c d

b e

a f

a c e f d e b d c b

(139)

c d e b

a f

a c e f d e b d c b a

(140)

Euler(u)

for alle (u,v) ∈ E

do if not visited(u,v)

then visited(u,v) ← true Euler(v)

u zu Euler-Tour

Laufzeit: O(|V| + |E|) (DFS)

(141)

Fragen?

(142)

zurück zur Aufgabe

Idee:

BFS von x liefert d[0][]

BFS von y liefert d[1][]

ein Knoten u liegt auf einem optimalen Pfad, falls

d[0][u] + d[1][u] = dx[0][y]

und d[0][u] einzigartig

Referenzen

ÄHNLICHE DOKUMENTE

Und wenn ich das tue, möchte ich auch nicht Toleranz in Anspruch nehmen müssen - Toleranz würde ja nur bedeuten, dass ich zwar schon was und womöglich begründet dagegen habe,

Wenngleich das Konzept quattromodaler Knoten einen gewissen Interpretationsspielraum lässt – so werden etwa die Pipeline, Normal- und Breitspur sowie die Binnen- und

Computer-gestützte Programme für das Ge- wichtsmanagmeent seien zwar weniger wirk- sam als persönliche Interventionen, aber auf jeden FAll besser als nichts und auch ange- sichts

Technische Universität München, Fakultät für Medizin, Klinik und Poliklinik für Derma- tologie und

  Dieser Knoten erzeugt in jedem Frame eine Transformation, die dafür sorgt, daß die lokale z-Achse zum aktuellen Viewpoint zeigt..   axisOfRotation wird im

  Felder mit einem Namen zzz, die den Access-Type exposedField haben, haben implizit den Namen zzz_changed, wenn sie als Ausgabe-Feld verwendet werden, und den Namen set_zzz,

(c) Ein Graph heißt stark-zusammenhängend, wenn jeder Knoten von jedem anderen Knoten durch einen Pfad erreichbar ist. Die Sprache L connected enthalte alle stark-

Für die Beurteilung von abweichenden Situationen wird angenommen, dass sich die Störwirkung in Abhängigkeit der Anzahl Stop &amp; Go Ereignisse verändert. Bei einer minimal