1 / 25

ACM ICPC Praktikum

ACM ICPC Praktikum. Kapitel 9: Graphdurchlauf. Übersicht. Arten von Graphen Datenstrukturen für Graphen Breitensuche Tiefensuche Zusammenhangskomponenten Topologische Sortierung. Arten von Graphen. Ein Graph G=(V,E) besteht aus einer Kontenmenge V und Kantenmenge E.

jalene
Télécharger la présentation

ACM ICPC Praktikum

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. ACM ICPC Praktikum Kapitel 9: Graphdurchlauf

  2. Übersicht • Arten von Graphen • Datenstrukturen für Graphen • Breitensuche • Tiefensuche • Zusammenhangskomponenten • Topologische Sortierung

  3. Arten von Graphen • Ein Graph G=(V,E) besteht aus einer Kontenmenge V und Kantenmenge E. • G ungerichtet: E µ { {u,v} | u,v 2 V} • Beispiel eines ungerichteten Graphen: Knoten Kante

  4. Arten von Graphen • G gerichtet: E µ V £ V • Beispiel eines gerichteten Graphen: • G gewichtet: Gewichtsfunktion für Knoten oder Kanten

  5. Arten von Graphen • G is azyklisch, wenn es keinen (gerichteten) Kreis hat, und sonst zyklisch • Beispiel eines gerichteten azyklischen Graphen (in der Literatur oft als DAG bez.)

  6. Arten von Graphen • G heißt einfach, wenn keine Kante doppelt vorkommt • Beispiel eines nicht-einfachen Graphen: • G ist beschriftet, falls die Knoten/Kanten Namen haben, sonst unbeschriftet

  7. Datenstrukturen für Graphen • G=(V,E) enthalte n Knoten und m Kanten • Adjazenzmatrix: Verwende n £ n-Matrix A[i,j] 2 {0,1} und setze A[i,j] auf 1 genau dann, wenn (i,j) bzw. {i,j} in E.Geeignet für dichte Graphen, d.h. m groß • Array von Adjazenzlisten: Vewende Array V der Größe n. V[i] speichert die Liste der benachbarten Knoten für Knoten i.Geeignet für dünne Graphen, d.h. m klein

  8. Datenstrukturen für Graphen • Array von Kanten: Verwende Array der Größe m, um alle Kanten abzuspeichern.Geeignet für sehr dünne Graphen. • Reine Pointerstruktur: Jeder Knoten ist ein Objekt mit Pointern, die Kanten repräsentieren, zu anderen Knoten.Geeignet für dynamische Graphen.

  9. Beispiel für Datenstruktur • #define MAXV 100 /* maximum number of vertices */ • #define MAXDEGREE 50 /* maximum outdegree of a vertex */ • typedef struct { • int edges[MAXV+1][MAXDEGREE]; /* adjacency info */ • int degree[MAXV+1]; /* outdegree of each vertex */ • int nvertices; /* number of vertices in the graph */ • int nedges; /* number of edges in the graph */ • } graph; • initialize_graph(graph *g) • { • int i; /* counter */ • g -> nvertices = 0; • g -> nedges = 0; • for (i=1; i<=MAXV; i++) g->degree[i] = 0; • }

  10. Beispiel für Datenstruktur • read_graph(graph *g, bool directed) • { • int i; /* counter */ • int m; /* number of edges */ • int x, y; /* vertices in edge (x,y) */ • initialize_graph(g); • scanf("%d %d",&(g->nvertices),&m); • for (i=1; i<=m; i++) { • scanf("%d %d",&x,&y); • insert_edge(g,x,y,directed); • } • }

  11. Beispiel für Datenstruktur • insert_edge(graph *g, int x, int y, bool directed) • { • if (g->degree[x] > MAXDEGREE) • printf("Warning: insertion(%d,%d) exceeds max degree\n",x,y); • g->edges[x][g->degree[x]] = y; • g->degree[x] ++; • if (directed == FALSE) • insert_edge(g,y,x,TRUE); • else • g->nedges ++; • }

  12. Beispiel für Datenstruktur • delete_edge(graph *g, int x, int y, bool directed) • { • int i; /* counter */ • for (i=0; i<g->degree[x]; i++) • if (g->edges[x][i] == y) { • g->degree[x] --; • g->edges[x][i] = g->edges[x][g->degree[x]]; • if (directed == FALSE) • delete_edge(g,y,x,TRUE); • return; • } • printf("Warning: deletion(%d,%d) not found in g.\n",x,y); • }

  13. Beispiel für Datenstruktur • print_graph(graph *g) • { • int i,j; /* counters */ • for (i=1; i<=g->nvertices; i++) { • printf("%d: ",i); • for (j=0; j<g->degree[i]; j++) • printf(" %d",g->edges[i][j]); • printf("\n"); • } • }

  14. Breitensuche • Problem: durchsuche Graph G=(V,E) systematisch nach Eigenschaften • Lösung:Breitensuche (breadth-first-search, BFS) oder Tiefensuche (depth-first-search, DFS). Jeder besuchte Knoten bzw. jede besuchte Kante wird markiert, um doppeltes Besuchen zu vermeiden.

  15. Breitensuche • bool processed[MAXV]; /* which vertices have been processed */ • bool discovered[MAXV]; /* which vertices have been found */ • int parent[MAXV]; /* discovery relation */ • bool finished = FALSE; /* if true, cut off search immediately */ • initialize_search(graph *g) • { • int i; /* counter */ • for (i=1; i<=g->nvertices; i++) { • processed[i] = discovered[i] = FALSE; • parent[i] = -1; • } • }

  16. Breitensuche • bfs(graph *g, int start) • { • queue q; /* queue of vertices to visit */ • int v; /* current vertex */ • int i; /* counter */ • init_queue(&q); • enqueue(&q,start); • discovered[start] = TRUE; • while (empty(&q) == FALSE) { • v = dequeue(&q); • process_vertex(v); • processed[v] = TRUE; • for (i=0; i<g->degree[v]; i++) • if (valid_edge(g->edges[v][i]) == TRUE) { • if (discovered[g->edges[v][i]] == FALSE) { • enqueue(&q,g->edges[v][i]); • discovered[g->edges[v][i]] = TRUE; • parent[g->edges[v][i]] = v; • } • if (processed[g->edges[v][i]] == FALSE) • process_edge(v,g->edges[v][i]); • } • } • }

  17. Breitensuche - Demo • process_vertex(int v) • { printf("processed vertex %d\n",v); } • process_edge(int x, int y) • { printf("processed edge (%d,%d)\n",x,y); } • bool valid_edge(int e) • { return (TRUE); } • main() • { • graph g; • int i; • read_graph(&g,FALSE); • print_graph(&g); • initialize_search(&g); • bfs(&g,1); • for (i=1; i<=g.nvertices; i++) printf(" %d",parent[i]); • printf("\n"); • for (i=1; i<=g.nvertices; i++) find_path(1,i,parent); • printf("\n"); • }

  18. Anwendung: Suche nach Pfad • Problem: finde Pfad von „start” nach “end”. • find_path(int start, int end, int parents[]) • { • if ((start == end) || (end == -1)) • printf("\n%d",start); • else { • find_path(start,parents[end],parents); • printf(" %d",end); • } • }

  19. Tiefensuche • dfs(graph *g, int v) • { • int i; /* counter */ • int y; /* successor vertex */ • if (finished) return; /* allow for search termination */ • discovered[v] = TRUE; • process_vertex(v); • for (i=0; i<g->degree[v]; i++) { • y = g->edges[v][i]; • if (valid_edge(g->edges[v][i]) == TRUE) { • if (discovered[y] == FALSE) { • parent[y] = v; • dfs(g,y); • } else • if (processed[y] == FALSE) • process_edge(v,y); • } • if (finished) return; • } • processed[v] = TRUE; • }

  20. Tiefensuche - Demo • process_vertex(int v) • { printf("processed vertex %d\n",v); } • process_edge(int x, int y) • { • if (parent[x] == y) printf("processed tree edge (%d,%d)\n",x,y); • else printf("processed back edge (%d,%d)\n",x,y); • } • bool valid_edge(int e) • { return (TRUE); } • main() • { graph g; • int i; • read_graph(&g,FALSE); • print_graph(&g); • initialize_search(&g); • dfs(&g,1); • for (i=1; i<=g.nvertices; i++) find_path(1,i,parent); • printf("\n"); • }

  21. Anwendung 1: suche Kreis • Problem: suche nach Kreis in ungerichtetem Graph • process_edge(int x, int y) • { • if (parent[x] != y) { /* found back edge! */ • printf(“Cycle from %d to %d:”, y, x); • find_path(y,x,parent); • finished = TRUE; • } } • process_vertex(int v) { }

  22. Anwendung 2: Zusammenhangskomponenten • Problem: finde Zusammenhangskomponenten in ungerichtetem Graph • connected_components(graph *g) • { • int c; /* component number */ • int i; /* counter */ • initialize_search(g); • c = 0; • for (i=1; i<=g->nvertices; i++) • if (discovered[i] == FALSE) { • c = c+1; • printf(“Component %d: “, c); • dfs(g,i); • printf(“\n”); • } } • process_vertex(int v) { print(“ %d”, v); } • process_edge(int x, int y) { }

  23. Anwendung 3: Topologisches Sortieren • Problem: sortiere Knoten in Reihe s, so dass für jede Kante (i,j) gilt: s(i) < s(j) • Lösung: • compute_indegrees(graph *g, int in[]) • { • int i,j; /* counters */ • for (i=1; i<=g->nvertices; i++) in[i] = 0; • for (i=1; i<=g->nvertices; i++) • for (j=0; j<g->degree[i]; j++) in[ g->edges[i][j] ] ++; • }

  24. Anwendung 3: Topologisches Sortieren • topsort(graph *g, int sorted[]) • { • int indegree[MAXV]; /* indegree of each vertex */ • queue zeroin; /* vertices of indegree 0 */ • int x, y; /* current and next vertex */ • int i, j; /* counters */ • compute_indegrees(g,indegree); • init_queue(&zeroin); • for (i=1; i<=g->nvertices; i++) • if (indegree[i] == 0) enqueue(&zeroin,i); • j=0; • while (empty(&zeroin) == FALSE) { • j = j+1; • x = dequeue(&zeroin); • sorted[j] = x; • for (i=0; i<g->degree[x]; i++) { • y = g->edges[x][i]; • indegree[y] --; • if (indegree[y] == 0) enqueue(&zeroin,y); • } • } • if (j != g->nvertices) • printf("Not a DAG -- only %d vertices found\n",j); • }

  25. Anwendung 3: Topologisches Sortieren • main() • { • graph g; • int out[MAXV]; • int i; • read_graph(&g,TRUE); • print_graph(&g); • topsort(&g,out); • for (i=1; i<=g.nvertices; i++) • printf(" %d",out[i]); • printf("\n"); • }

More Related