41
ACM ICPC Praktikum Kapitel 10: Graphalgorithmen

ACM ICPC Praktikum

  • Upload
    amie

  • View
    35

  • Download
    0

Embed Size (px)

DESCRIPTION

ACM ICPC Praktikum. Kapitel 10: Graphalgorithmen. Übersicht. Bäume Minimale Spannbäume Zusammenhang Kürzeste Wege Kreise Planare Graphen Netzwerkfluss und bipartites Matching. Bäume. Ein Baum ist ein zusammen - hängender Graph, der keine Kreise enthält. - PowerPoint PPT Presentation

Citation preview

Page 1: ACM ICPC  Praktikum

ACM ICPC Praktikum

Kapitel 10: Graphalgorithmen

Page 2: ACM ICPC  Praktikum

Übersicht

• Bäume

• Minimale Spannbäume

• Zusammenhang

• Kürzeste Wege

• Kreise

• Planare Graphen

• Netzwerkfluss und bipartites Matching

Page 3: ACM ICPC  Praktikum

Bä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.

Page 4: ACM ICPC  Praktikum

Bäume

• Gewurzelter Baum:gerichteter Baum, in dem jeder Knoten bis auf Wurzel Eingrad 1 hat.

• Binärer Baum:Jeder 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.

Page 5: ACM ICPC  Praktikum

Minimaler Spannbaum

• Gegeben: Graph G=(V,E) mit Kantenkosten c:E ! 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

Page 6: ACM ICPC  Praktikum

Prims Algorithmus

1. #define MAXV 100 /* maximum number of vertices */2. #define MAXDEGREE 50 /* maximum outdegree of a vertex */

3. typedef struct {4. int v; /* neighboring vertex */5. int weight; /* edge weight */6. } edge;

7. typedef struct {8. edge edges[MAXV+1][MAXDEGREE]; /* adjacency info */9. int degree[MAXV+1]; /* outdegree of each vertex */10. int nvertices; /* number of vertices in the graph */11. int nedges; /* number of edges in the graph */12. } graph;

Page 7: ACM ICPC  Praktikum

Prims Algorithmus1. int parent[MAXV]; /* discovery relation */

2. prim(graph *g, int start)3. {4. int i,j; /* counters */5. bool intree[MAXV]; /* is the vertex in the tree yet? */6. int distance[MAXV]; /* distance vertex is from start */7. int v; /* current vertex to process */8. int w; /* candidate next vertex */9. int weight; /* edge weight */10. int dist; /* best current distance from start */

11. for (i=1; i<=g->nvertices; i++) {12. intree[i] = FALSE;13. distance[i] = MAXINT;14. parent[i] = -1;15. }

16. distance[start] = 0;17. v = start;

Page 8: ACM ICPC  Praktikum

Prims Algorithmus1. while (intree[v] == FALSE) {2. intree[v] = TRUE;3. for (i=0; i<g->degree[v]; i++) {4. w = g->edges[v][i].v;5. weight = g->edges[v][i].weight;6. if ((distance[w] > weight) && (intree[w] == FALSE)) {7. distance[w] = weight;8. parent[w] = v;9. }10. }

11. v = 1;12. dist = MAXINT;13. for (i=1; i<=g->nvertices; i++) 14. if ((intree[i] == FALSE) && (dist > distance[i])) {15. dist = distance[i];16. v = i;17. }18. }19. }

Page 9: ACM ICPC  Praktikum

Prims Algorithmus1. main()2. {3. graph g;4. int i;

5. read_graph(&g,FALSE);

6. prim(&g,1);

7. printf("Out of Prim\n");

8. for (i=1; i<=g.nvertices; i++) {9. /*printf(" %d parent=%d\n",i,parent[i]);*/10. find_path(1,i,parent);11. }12. printf("\n");13. }

Page 10: ACM ICPC  Praktikum

MST 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)

Page 11: ACM ICPC  Praktikum

Zusammenhang

• 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.

Page 12: ACM ICPC  Praktikum

Test 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 >=k hat.

Page 13: ACM ICPC  Praktikum

Kürzeste Wege

• Gegeben: Graph G=(V,E) mit Kantenkosten c:E ! 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

Page 14: ACM ICPC  Praktikum

Dijkstras Algorithmus1. int parent[MAXV]; /* discovery relation */

2. dijkstra(graph *g, int start) /* was prim(g,start) */3. {4. int i,j; /* counters */5. bool intree[MAXV]; /* is the vertex in the tree yet? */6. int distance[MAXV]; /* distance vertex is from start */7. int v; /* current vertex to process */8. int w; /* candidate next vertex */9. int weight; /* edge weight */10. int dist; /* best current distance from start */

11. for (i=1; i<=g->nvertices; i++) {12. intree[i] = FALSE;13. distance[i] = MAXINT;14. parent[i] = -1;15. }

16. distance[start] = 0;17. v = start;

Page 15: ACM ICPC  Praktikum

Dijkstras Algorithmus1. while (intree[v] == FALSE) {2. intree[v] = TRUE;3. for (i=0; i<g->degree[v]; i++) {4. w = g->edges[v][i].v;5. weight = g->edges[v][i].weight;6. if (distance[w] > (distance[v]+weight)) {7. distance[w] = distance[v]+weight;8. parent[w] = v;9. }10. }

11. v = 1;12. dist = MAXINT;13. for (i=1; i<=g->nvertices; i++) 14. if ((intree[i] == FALSE) && (dist > distance[i])) {15. dist = distance[i];16. v = i;17. }18. }19. /*for (i=1; i<=g->nvertices; i++) printf("%d %d\n",i,distance[i]);*/20. }

Page 16: ACM ICPC  Praktikum

Dijkstras Algorithmus1. main()2. {3. graph g;4. int i;

5. read_graph(&g,FALSE);6. dijkstra(&g,1);

7. for (i=1; i<=g.nvertices; i++)8. find_path(1,i,parent);9. printf("\n");

10. }

Page 17: ACM ICPC  Praktikum

Floyd-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 edges[MAXV][MAXDEGREE]; /* adjacency info */• int degree[MAXV]; /* outdegree of each vertex */• int nvertices; /* number of vertices in the graph */• int nedges; /* number of edges in the graph */• } graph;

• typedef struct {• int weight[MAXV+1][MAXV+1]; /* adjacency/weight info */• int nvertices; /* number of vertices in the graph */• } adjacency_matrix;

Page 18: ACM ICPC  Praktikum

Floyd-Warshall Algorithmus1. initialize_adjacency_matrix(adjacency_matrix *g)2. {3. int i,j; /* counters */

4. g -> nvertices = 0;5. for (i=1; i<=MAXV; i++)6. for (j=1; j<=MAXV; j++)7. g->weight[i][j] = MAXINT;8. }

9. read_adjacency_matrix(adjacency_matrix *g, bool directed)10. {11. int i; /* counter */12. int m; /* number of edges */13. int x,y,w; /* placeholder for edge and weight */

14. initialize_adjacency_matrix(g);15. scanf("%d %d\n",&(g->nvertices),&m);

16. for (i=1; i<=m; i++) {17. scanf("%d %d %d\n",&x,&y,&w);18. g->weight[x][y] = w;19. if (directed==FALSE) g->weight[y][x] = w;20. }21. }

Page 19: ACM ICPC  Praktikum

Floyd-Warshall Algorithmus1. print_graph(adjacency_matrix *g)2. {3. int i,j; /* counters */

4. for (i=1; i<=g->nvertices; i++) {5. printf("%d: ",i);6. for (j=1; j<=g->nvertices; j++)7. if (g->weight[i][j] < MAXINT)8. printf(" %d",j);9. printf("\n");10. }11. }

12. print_adjacency_matrix(adjacency_matrix *g)13. {14. int i,j; /* counters */

15. for (i=1; i<=g->nvertices; i++) {16. printf("%3d: ",i);17. for (j=1; j<=g->nvertices; j++)18. printf(" %3d",g->weight[i][j]);19. printf("\n");20. }• }

Page 20: ACM ICPC  Praktikum

Floyd-Warshall Algorithmus1. floyd(adjacency_matrix *g)2. {3. int i,j; /* dimension counters */4. int k; /* intermediate vertex counter */5. int through_k; /* distance through vertex k */

6. for (k=1; k<=g->nvertices; k++)7. for (i=1; i<=g->nvertices; i++)8. for (j=1; j<=g->nvertices; j++) {9. through_k = g->weight[i][k]+g-

>weight[k][j];10. if (through_k < g->weight[i][j])11. g->weight[i][j] = through_k;12. }13. }

Page 21: ACM ICPC  Praktikum

Floyd-Warshall Algorithmus1. main()2. {3. adjacency_matrix g;

4. read_adjacency_matrix(&g,FALSE);5. print_graph(&g);

6. floyd(&g);

7. print_adjacency_matrix(&g);

8. }

Page 22: ACM ICPC  Praktikum

Kreise

• 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.

Page 23: ACM ICPC  Praktikum

Eulerkreis

• Eulerkreis im ungerichteten Graphen:Existiert, wenn alle Knoten geraden Grad haben.Algorithmus: Beginne bei beliebigem Knoten, erweitere Kreis um beliebige Kante, bis wieder am Ausgangspunkt.Wiederholung ergibt kantendisjunkte Kreise, die beliebige verschmolzen werden können.

• Eulerkreis im gerichteten Graphen:Existiert, falls für jeden Knoten der Eingrad gleich dem Ausgrad ist. Dann wie oben.

Page 24: ACM ICPC  Praktikum

Hamiltonscher 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.

Page 25: ACM ICPC  Praktikum

Planare 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-m+f=2.• Jeder planare Graph erfüllt m <= 3n-6.• Ein Graph ist planar genau dann, wenn er

keinen K3,3 oder K5 als Graphminor enthält.

Page 26: ACM ICPC  Praktikum

Netzwerkfluss

• Gegeben: gerichteter Graph G=(V,E) mit Kantenkapazitäten c:E ! IR+ und Quell-Ziel-Paar (s,t)

• Gesucht: Fluss f:E ! 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) <= c(e) für alle e 2 E

• Flusswert von f ist (s,w) f(s,w) - (u,s) f(u,s)

Page 27: ACM ICPC  Praktikum

Netzwerkfluss

• O.B.d.A. sei G ein einfacher gerichteter Graph, ansonsten Transformation:

• Residuales Netzwerk von f: G’=(V,E’) mit c’:E ! 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

Page 28: ACM ICPC  Praktikum

Netzwerkfluss

• Augmentierender Pfad p=(v1,…,vk) in G’: Pfad mit positiven Kantenkosten

• Residuale Kapazität von p: cp = mini c’(vi,vi+1)

• Neuer Fluss f’ =f+p: 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’ > Flusswert von f und f maximal , kein augm. Pfad in G’

Page 29: ACM ICPC  Praktikum

Ford-Fulkerson Algorithmus1. #define MAXV 100 /* maximum number of vertices */2. #define MAXDEGREE 50 /* maximum outdegree of a vertex

*/

3. typedef struct {4. int v; /* neighboring vertex */5. int capacity; /* capacity of edge */6. int flow; /* flow through edge */7. int residual; /* residual capacity of edge */8. } edge;

9. typedef struct {10. edge edges[MAXV][MAXDEGREE]; /* adjacency info */11. int degree[MAXV]; /* outdegree of each vertex */12. int nvertices; /* number of vertices in the graph

*/13. int nedges; /* number of edges in the graph */14. } flow_graph;

Page 30: ACM ICPC  Praktikum

Ford-Fulkerson Algorithmus1. main()2. {3. flow_graph g; /* graph to analyze */4. int source, sink; /* source and sink vertices */5. int flow; /* total flow */6. int i; /* counter */

7. scanf("%d %d",&source,&sink);8. read_flow_graph(&g,TRUE);

9. netflow(&g,source,sink);

10. print_flow_graph(&g);

11. flow = 0;12. for (i=0; i<g.nvertices; i++)13. flow += g.edges[source][i].flow;

14. printf("total flow = %d\n",flow);15. }

Page 31: ACM ICPC  Praktikum

Ford-Fulkerson Algorithmus1. initialize_graph(g)2. flow_graph *g; /* graph to initialize */3. {4. int i; /* counter */

5. g -> nvertices = 0;6. g -> nedges = 0;7. for (i=0; i<MAXV; i++) g->degree[i] = 0;8. }

9. read_flow_graph(g,directed)10. flow_graph *g; /* graph to initialize */11. bool directed; /* is this graph directed? */12. {13. int i; /* counter */14. int m; /* number of edges */15. int x,y,w; /* placeholder for edge and weight */

16. initialize_graph(g);17. scanf("%d %d\n",&(g->nvertices),&m);18. for (i=1; i<=m; i++) {19. scanf("%d %d %d\n",&x,&y,&w);20. insert_flow_edge(g,x,y,directed,w);21. }22. }

Page 32: ACM ICPC  Praktikum

Ford-Fulkerson Algorithmus1. insert_flow_edge(flow_graph *g, int x, int y, bool directed, int w)2. {3. if (g->degree[x] > MAXDEGREE)4. printf("Warning: insertion(%d,%d) exceeds degree bound\n",x,y);

5. g->edges[x][g->degree[x]].v = y;6. g->edges[x][g->degree[x]].capacity = w;7. g->edges[x][g->degree[x]].flow = 0;8. g->edges[x][g->degree[x]].residual = w;9. g->degree[x] ++;

10. if (directed == FALSE)11. insert_flow_edge(g,y,x,TRUE,w);12. else13. g->nedges ++;14. }

Page 33: ACM ICPC  Praktikum

Ford-Fulkerson Algorithmus1. edge *find_edge(flow_graph *g, int x, int y)2. {3. int i; /* counter */

4. for (i=0; i<g->degree[x]; i++) 5. if (g->edges[x][i].v == y) 6. return( &g->edges[x][i] );

7. return(NULL);8. }

9. add_residual_edges(flow_graph *g)10. {11. int i,j; /* counters */

12. for (i=1; i<=g->nvertices; i++) 13. for (j=0; j<g->degree[i]; j++)14. if (find_edge(g,g->edges[i][j].v,i) == NULL)15. insert_flow_edge(g,g->edges[i][j].v,i,TRUE,0);16. }

Page 34: ACM ICPC  Praktikum

Ford-Fulkerson Algorithmus1. print_flow_graph(flow_graph *g)2. {3. int i,j; /* counters */

4. for (i=1; i<=g->nvertices; i++) {5. printf("%d: ",i);6. for (j=0; j<g->degree[i]; j++)7. printf(" %d(%d,%d,%d)",g->edges[i][j].v,8. g->edges[i][j].capacity,9. g->edges[i][j].flow,10. g->edges[i][j].residual);11. printf("\n");12. }13. }

14. bool processed[MAXV]; /* which vertices have been processed */15. bool discovered[MAXV]; /* which vertices have been found */16. int parent[MAXV]; /* discovery relation */

17. bool finished = FALSE; /* if true, cut off search immediately */

Page 35: ACM ICPC  Praktikum

Ford-Fulkerson Algorithmus

1. initialize_search(g)2. flow_graph *g; /* graph to

traverse */3. {4. int i; /* counter */

5. for (i=1; i<=g->nvertices; i++) {6. processed[i] = FALSE;7. discovered[i] = FALSE;8. parent[i] = -1;9. }10. }

Page 36: ACM ICPC  Praktikum

Ford-Fulkerson Algorithmus1. bfs(flow_graph *g, int start)2. {3. queue q; /* queue of vertices to visit */4. int v; /* current vertex */5. int i; /* counter */

6. init_queue(&q);7. enqueue(&q,start);8. discovered[start] = TRUE;

9. while (empty(&q) == FALSE) {10. v = dequeue(&q);11. process_vertex(v);12. processed[v] = TRUE;13. for (i=0; i<g->degree[v]; i++) 14. if (valid_edge(g->edges[v][i]) == TRUE) {15. if (discovered[g->edges[v][i].v] == FALSE) {16. enqueue(&q,g->edges[v][i].v);17. discovered[g->edges[v][i].v] = TRUE;18. parent[g->edges[v][i].v] = v;19. }20. if (processed[g->edges[v][i].v] == FALSE) 21. process_edge(v,g->edges[v][i].v);22. }23. }24. }

Page 37: ACM ICPC  Praktikum

Ford-Fulkerson Algorithmus1. bool valid_edge(edge e)2. {3. if (e.residual > 0) return (TRUE);4. else return(FALSE);5. }

6. process_vertex(v)7. int v; /* vertex to process */8. {9. }

10.process_edge(x,y)11. int x,y; /* edge to process */12. {13. }

Page 38: ACM ICPC  Praktikum

Ford-Fulkerson Algorithmus1. find_path(start,end,parents)2. int start; /* first vertex on path */3. int end; /* last vertex on path */4. int parents[]; /* array of parent pointers */5. {6. if ((start == end) || (end == -1))7. printf("\n%d",start);8. else {9. find_path(start,parents[end],parents);10. printf(" %d",end);11. }12. }

13. int path_volume(flow_graph *g, int start, int end, int parents[])14. {15. edge *e; /* edge in question */16. edge *find_edge();

17. if (parents[end] == -1) return(0)18. e = find_edge(g,parents[end],end);19. if (start == parents[end])20. return(e->residual);21. else22. return( min(path_volume(g,start,parents[end],parents), e->residual) );23. }

Page 39: ACM ICPC  Praktikum

Ford-Fulkerson Algorithmus1. augment_path(flow_graph *g, int start, int end, int parents[], int volume)2. {3. edge *e; /* edge in question */4. edge *find_edge();

5. if (start == end) return;

6. e = find_edge(g,parents[end],end);7. e->flow += volume;8. e->residual -= volume;9.10. e = find_edge(g,end,parents[end]);11. e->residual += volume;

12. augment_path(g,start,parents[end],parents,volume);13. }

Page 40: ACM ICPC  Praktikum

Ford-Fulkerson Algorithmus1. netflow(flow_graph *g, int source, int sink)2. {3. int volume; /* weight of the augmenting path */

4. add_residual_edges(g);

5. initialize_search(g);6. bfs(g,source);

7. volume = path_volume(g, source, sink, parent);

8. while (volume > 0) {9. augment_path(g,source,sink,parent,volume);10. initialize_search(g);11. bfs(g,source);12. volume = path_volume(g, source, sink, parent);13. }14. }

Page 41: ACM ICPC  Praktikum

Anwendungen

• 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)