Title: ACM ICPC Praktikum
1ACM ICPC Praktikum
- Kapitel 10 Graphalgorithmen
2Übersicht
- Bäume
- Minimale Spannbäume
- Zusammenhang
- Kürzeste Wege
- Kreise
- Planare Graphen
- Netzwerkfluss und bipartites Matching
3Bäume
- Ein Baum ist ein zusammen-hängender Graph, der
keine Kreise enthält. - Jeder Baum mit n Knoten hat also genau n-1
Kanten. - Ein Baum hat oft einen ausge-zeichneten Knoten,
der die Wurzel repräsentiert. - Jeder Knoten mit Grad 1 im Baum heißt Blatt.
4Bäume
- Gewurzelter Baumgerichteter Baum, in dem jeder
Knoten bis auf Wurzel Eingrad 1 hat. - Binärer BaumJeder Knoten hat Ausgrad 2 oder 0.
- Spannbaum eines Graphen G(V,E) Teilgraph von
G, der ein Baum ist und alle Knoten von G
enthält.
5Minimaler Spannbaum
- Gegeben Graph G(V,E) mit Kantenkosten cE ! IR
- Gesucht Spannbaum T in G mit minimaler Summe der
Kantenkosten - Algorithmen Starte mit leerer Kantenmenge.
Wiederhole, bis Spannbaum erreicht - Kruskal füge Kante mit minimalem Gewicht unter
Wahrung der Kreisfreiheit hinzu - Prim erweitere Baum um minimale Kante
6Prims Algorithmus
- define MAXV 100 / maximum number of vertices /
- define MAXDEGREE 50 / maximum outdegree of a
vertex / - typedef struct
- int v / neighboring vertex /
- int weight / edge weight /
- edge
- typedef struct
- edge edgesMAXV1MAXDEGREE / adjacency info
/ - int degreeMAXV1 / outdegree of each vertex
/ - int nvertices / number of vertices in the
graph / - int nedges / number of edges in the graph /
- graph
7Prims Algorithmus
- int parentMAXV / discovery
relation / - prim(graph g, int start)
-
- int i,j / counters /
- bool intreeMAXV / is the vertex in the tree
yet? / - int distanceMAXV / distance vertex is from
start / - int v / current vertex to process /
- int w / candidate next vertex /
- int weight / edge weight /
- int dist / best current distance from start
/ - for (i1 iltg-gtnvertices i)
- intreei FALSE
- distancei MAXINT
- parenti -1
-
- distancestart 0
8Prims Algorithmus
- while (intreev FALSE)
- intreev TRUE
- for (i0 iltg-gtdegreev i)
- w g-gtedgesvi.v
- weight g-gtedgesvi.weight
- if ((distancew gt weight) (intreew
FALSE)) - distancew weight
- parentw v
-
-
- v 1
- dist MAXINT
- for (i1 iltg-gtnvertices i)
- if ((intreei FALSE) (dist gt
distancei)) - dist distancei
- v i
-
-
9Prims Algorithmus
- main()
-
- graph g
- int i
- read_graph(g,FALSE)
- prim(g,1)
- printf("Out of Prim\n")
- for (i1 iltg.nvertices i)
- /printf(" d parentd\n",i,parenti)/
- find_path(1,i,parent)
-
- printf("\n")
-
10MST Probleme
- Maximum Spanning Tree Maximiere Kosten eines
Spannbaums. - Minimum Product Spanning Tree Minimiere Produkt
der Kantenkosten( minimiere Summe der
Logarithmen) - Minimum Bottleneck Spanning Tree Minimiere
maximale Kantenkosten(MST minimiert auch max.
Kantenkosten)
11Zusammenhang
- Ein ungerichteter (gerichteter) Graph ist (stark)
zusammenhängend, wenn es einen ungerichteten
(gerichteten) Weg zwischen zwei beliebigen
Knotenpaaren gibt. - Jeder Graph, der auch nach Löschung eines
beliebigen Knotens noch zusammenhängend ist,
heißt zweifach zusammenhängend. - Eine Kante, dessen Löschung den Graphen in zwei
Teilgraphen zerteilt, heißt Brücke.
12Test auf Zusammenhang
- Einfacher Zusammenhang DFS, BFS
- Starker Zusammenhang Finde gerichteten Kreis
mittels DFS. Schrumpfe solch einen Kreis zu einem
einzelnen Knoten und wiederhole, bis kein
gerichteter Kreis mehr gefunden. Ergibt einzelnen
Knoten Graph start zusammenhängend. - k-facher Zusammenhang Teste, ob jedes Knotenpaar
Fluss der Größe gtk hat.
13Kürzeste Wege
- Gegeben Graph G(V,E) mit Kantenkosten cE ! IR
- Weg von v nach w ist kürzester Weg, wenn Summe
der Kantenkosten minimal. - Single-source-shortest-path DijkstraIdee
arbeite ähnlich zu Prim, um einen
kürzeste-Wege-Baum aufzubauen - All-pairs-shortest-path Floyd-WarshallIdee
verwende Matrixmultiplikation
14Dijkstras Algorithmus
- int parentMAXV / discovery
relation / - dijkstra(graph g, int start) / was
prim(g,start) / -
- int i,j / counters /
- bool intreeMAXV / is the vertex in the tree
yet? / - int distanceMAXV / distance vertex is from
start / - int v / current vertex to process /
- int w / candidate next vertex /
- int weight / edge weight /
- int dist / best current distance from start
/ - for (i1 iltg-gtnvertices i)
- intreei FALSE
- distancei MAXINT
- parenti -1
-
- distancestart 0
15Dijkstras Algorithmus
- while (intreev FALSE)
- intreev TRUE
- for (i0 iltg-gtdegreev i)
- w g-gtedgesvi.v
- weight g-gtedgesvi.weight
- if (distancew gt (distancevweight))
- distancew distancevweight
- parentw v
-
-
- v 1
- dist MAXINT
- for (i1 iltg-gtnvertices i)
- if ((intreei FALSE) (dist gt
distancei)) - dist distancei
- v i
-
-
16Dijkstras Algorithmus
- main()
-
- graph g
- int i
- read_graph(g,FALSE)
- dijkstra(g,1)
- for (i1 iltg.nvertices i)
- find_path(1,i,parent)
- printf("\n")
-
17Floyd-Warshall Algorithmus
- define MAXV 100 / maximum number of vertices
/ - define MAXDEGREE 50 / maximum outdegree of a
vertex / - define MAXINT 100007
- typedef struct
- int v / neighboring vertex /
- int weight / edge weight /
- bool in / is the edge "in" the solution? /
- edge
- typedef struct
- edge edgesMAXVMAXDEGREE / adjacency info
/ - int degreeMAXV / outdegree of each vertex
/ - int nvertices / number of vertices in the
graph / - int nedges / number of edges in the graph /
- graph
- typedef struct
18Floyd-Warshall Algorithmus
- initialize_adjacency_matrix(adjacency_matrix g)
-
- int i,j / counters /
- g -gt nvertices 0
- for (i1 iltMAXV i)
- for (j1 jltMAXV j)
- g-gtweightij MAXINT
-
- read_adjacency_matrix(adjacency_matrix g, bool
directed) -
- int i / counter /
- int m / number of edges /
- int x,y,w / placeholder for edge and weight
/ - initialize_adjacency_matrix(g)
- scanf("d d\n",(g-gtnvertices),m)
19Floyd-Warshall Algorithmus
- print_graph(adjacency_matrix g)
-
- int i,j / counters /
- for (i1 iltg-gtnvertices i)
- printf("d ",i)
- for (j1 jltg-gtnvertices j)
- if (g-gtweightij lt MAXINT)
- printf(" d",j)
- printf("\n")
-
-
- print_adjacency_matrix(adjacency_matrix g)
-
- int i,j /
counters / - for (i1 iltg-gtnvertices i)
- printf("3d ",i)
20Floyd-Warshall Algorithmus
- floyd(adjacency_matrix g)
-
- int i,j / dimension counters /
- int k / intermediate vertex counter /
- int through_k / distance through vertex k /
- for (k1 kltg-gtnvertices k)
- for (i1 iltg-gtnvertices i)
- for (j1 jltg-gtnvertices j)
- through_k g-gtweightikg-gtweightkj
- if (through_k lt g-gtweightij)
- g-gtweightij through_k
-
21Floyd-Warshall Algorithmus
- main()
-
- adjacency_matrix g
- read_adjacency_matrix(g,FALSE)
- print_graph(g)
- floyd(g)
- print_adjacency_matrix(g)
22Kreise
- Alle Graphen, die keine Bäume sind, enthalten
Kreise. - Eulerkreis Kreis, der jede Kante genau einmal
durchläuft. - Hamiltonscher Kreis Kreis, der jeden Knoten
genau einmal durchläuft.
23Eulerkreis
- Eulerkreis im ungerichteten GraphenExistiert,
wenn alle Knoten geraden Grad haben.Algorithmus
Beginne bei beliebigem Knoten, erweitere Kreis um
beliebige Kante, bis wieder am Ausgangspunkt.Wied
erholung ergibt kantendisjunkte Kreise, die
beliebige verschmolzen werden können. - Eulerkreis im gerichteten GraphenExistiert,
falls für jeden Knoten der Eingrad gleich dem
Ausgrad ist. Dann wie oben.
24Hamiltonscher Kreis
- NP-vollständiges Problem, d.h. es gibt aller
Voraussicht nach keinen Polynomialzeitalgorithmus
dafür. - Backtracking (mittels Durchlauf aller möglichen
Knotenpermutationen) kann verwendet werden, falls
Graph genügend klein ist.
25Planare Graphen
- Ein Graph ist planar, falls die Knoten und Kanten
so in 2D-Raum eingebettet werden können, dass es
keine Kantenüberschneidungen gibt. - Ein Baum ist ein planarer Graph.
- Sei n Anzahl Knoten, m Anzahl Kanten und f Anzahl
Facetten, dann gilt n-mf2. - Jeder planare Graph erfüllt m lt 3n-6.
- Ein Graph ist planar genau dann, wenn er keinen
K3,3 oder K5 als Graphminor enthält.
26Netzwerkfluss
- Gegeben gerichteter Graph G(V,E) mit
Kantenkapazitäten cE ! IR und Quell-Ziel-Paar
(s,t) - Gesucht Fluss fE ! IR mit maximalem Flusswert
von s nach t. - Fluss f ist legal, falls
- ?(u,v) f(u,v) ?(v,w) f(v,w) für alle v 2 V n
s,t - f(e) lt c(e) für alle e 2 E
- Flusswert von f ist ?(s,w) f(s,w) - ?(u,s) f(u,s)
27Netzwerkfluss
- O.B.d.A. sei G ein einfacher gerichteter Graph,
ansonsten Transformation - Residuales Netzwerk von f G(V,E) mit cE !
IR, wobei c(u,v)c(u,v)-f(u,v) falls (u,v) 2 E,
c(u,v) f(v,u) falls (v,u) 2 E, und sonst
c(u,v) 0.
neu
28Netzwerkfluss
- Augmentierender Pfad p(v1,,vk) in G Pfad mit
positiven Kantenkosten - Residuale Kapazität von p cp mini c(vi,vi1)
- Neuer Fluss f fp f(u,v) f(u,v)cp falls
(u,v) 2 p undf(u,v) f(u,v)-cp falls (v,u) 2 p - Es gilt Flusswert von f gt Flusswert von f und f
maximal , kein augm. Pfad in G
29Ford-Fulkerson Algorithmus
- define MAXV 100 / maximum number of vertices
/ - define MAXDEGREE 50 / maximum outdegree of a
vertex / - typedef struct
- int v / neighboring vertex /
- int capacity / capacity of edge /
- int flow / flow through edge /
- int residual / residual capacity of edge /
- edge
- typedef struct
- edge edgesMAXVMAXDEGREE / adjacency info
/ - int degreeMAXV / outdegree of each vertex
/ - int nvertices / number of vertices in the
graph / - int nedges / number of edges in the graph /
- flow_graph
30Ford-Fulkerson Algorithmus
- main()
-
- flow_graph g / graph to analyze /
- int source, sink / source and sink vertices
/ - int flow / total flow /
- int i / counter /
- scanf("d d",source,sink)
- read_flow_graph(g,TRUE)
- netflow(g,source,sink)
- print_flow_graph(g)
- flow 0
- for (i0 iltg.nvertices i)
- flow g.edgessourcei.flow
- printf("total flow d\n",flow)
31Ford-Fulkerson Algorithmus
- initialize_graph(g)
- flow_graph g / graph to initialize /
-
- int i / counter /
- g -gt nvertices 0
- g -gt nedges 0
- for (i0 iltMAXV i) g-gtdegreei 0
-
- read_flow_graph(g,directed)
- flow_graph g / graph to initialize /
- bool directed / is this graph directed? /
-
- int i / counter /
- int m / number of edges /
- int x,y,w / placeholder for edge and weight
/ - initialize_graph(g)
32Ford-Fulkerson Algorithmus
- insert_flow_edge(flow_graph g, int x, int y,
bool directed, int w) -
- if (g-gtdegreex gt MAXDEGREE)
- printf("Warning insertion(d,d) exceeds
degree bound\n",x,y) - g-gtedgesxg-gtdegreex.v y
- g-gtedgesxg-gtdegreex.capacity w
- g-gtedgesxg-gtdegreex.flow 0
- g-gtedgesxg-gtdegreex.residual w
- g-gtdegreex
- if (directed FALSE)
- insert_flow_edge(g,y,x,TRUE,w)
- else
- g-gtnedges
-
33Ford-Fulkerson Algorithmus
- edge find_edge(flow_graph g, int x, int y)
-
- int i / counter /
- for (i0 iltg-gtdegreex i)
- if (g-gtedgesxi.v y)
- return( g-gtedgesxi )
- return(NULL)
-
- add_residual_edges(flow_graph g)
-
- int i,j / counters /
- for (i1 iltg-gtnvertices i)
- for (j0 jltg-gtdegreei j)
- if (find_edge(g,g-gtedgesij.v,i) NULL)
34Ford-Fulkerson Algorithmus
- print_flow_graph(flow_graph g)
-
- int i,j / counters /
- for (i1 iltg-gtnvertices i)
- printf("d ",i)
- for (j0 jltg-gtdegreei j)
- printf(" d(d,d,d)",g-gtedgesij.v,
- g-gtedgesij.capacity,
- g-gtedgesij.flow,
- g-gtedgesij.residual)
- printf("\n")
-
-
- bool processedMAXV / which vertices have been
processed / - bool discoveredMAXV / which vertices
have been found / - int parentMAXV / discovery relation /
35Ford-Fulkerson Algorithmus
- initialize_search(g)
- flow_graph g / graph to traverse /
-
- int i /
counter / - for (i1 iltg-gtnvertices i)
- processedi FALSE
- discoveredi FALSE
- parenti -1
-
-
36Ford-Fulkerson Algorithmus
- bfs(flow_graph g, int start)
-
- queue q / queue of vertices to visit /
- int v / current vertex /
- int i / counter /
- init_queue(q)
- enqueue(q,start)
- discoveredstart TRUE
- while (empty(q) FALSE)
- v dequeue(q)
- process_vertex(v)
- processedv TRUE
- for (i0 iltg-gtdegreev i)
- if (valid_edge(g-gtedgesvi) TRUE)
- if (discoveredg-gtedgesvi.v FALSE)
- enqueue(q,g-gtedgesvi.v)
- discoveredg-gtedgesvi.v TRUE
37Ford-Fulkerson Algorithmus
- bool valid_edge(edge e)
-
- if (e.residual gt 0) return (TRUE)
- else return(FALSE)
-
- process_vertex(v)
- int v / vertex to process /
-
-
- process_edge(x,y)
- int x,y / edge
to process / -
-
38Ford-Fulkerson Algorithmus
- find_path(start,end,parents)
- int start / first vertex on path /
- int end / last vertex on path /
- int parents / array of parent pointers /
-
- if ((start end) (end -1))
- printf("\nd",start)
- else
- find_path(start,parentsend,parents)
- printf(" d",end)
-
-
- int path_volume(flow_graph g, int start, int
end, int parents) -
- edge e / edge in question /
- edge find_edge()
- if (parentsend -1) return(0)
39Ford-Fulkerson Algorithmus
- augment_path(flow_graph g, int start, int end,
int parents, int volume) -
- edge e / edge in question /
- edge find_edge()
- if (start end) return
- e find_edge(g,parentsend,end)
- e-gtflow volume
- e-gtresidual - volume
-
- e find_edge(g,end,parentsend)
- e-gtresidual volume
- augment_path(g,start,parentsend,parents,volume)
40Ford-Fulkerson Algorithmus
- netflow(flow_graph g, int source, int sink)
-
- int volume / weight of the augmenting path
/ - add_residual_edges(g)
- initialize_search(g)
- bfs(g,source)
- volume path_volume(g, source, sink, parent)
- while (volume gt 0)
- augment_path(g,source,sink,parent,volume)
- initialize_search(g)
- bfs(g,source)
- volume path_volume(g, source, sink, parent)
-
41Anwendungen
- Maximum Matching in bipartiten Graphen.
- Gegeben Graph G(V,E)
- Matching Teilmenge E ½ E, so dass jeder Knoten
max. Grad 1 hat. - G bipartit genau dann, wenn zweifärbbar (d.h.
zwei Farben reichen, Knoten so zu färben, dass
keine zwei adjazenten Knoten dieselbe Farbe haben)