09/06/2015

Desafios de Programação TCC-00.254 | Turma A-1

Conteúdo Grafos

Professor Leandro Augusto Frata Fernandes [email protected]

Material disponível em http://www.ic.uff.br/~laffernandes/teaching/2015.1/tcc-00.254

Grafos



Parte 1 Estruturas de dados Travessia em largura e profundidade Ordenação topológica



Parte 2 Árvore geradora mínima Caminho mais curto Fluxo de rede Etc. TCC-00.254 Desafios de Programação

2

1

09/06/2015

Leitura Sugerida • • • •

Art of Programming Contest AREFIN, A. S. 2nd ed. Gyankosh Prokashoni: 2006 Capítulo 12 Introduction to Algorithms CORMEN, T. H. et al. The MIT Press: 2009 Capítulos 6 Competitive Programming 2 / 3 HALIM, S.; HALIM, F. Lulu: 2012 / 2013 Capítulos 2 (algumas partes) e 4 Programming Challenges SKIENA, S.S.; REVILÇA, M.A. Springer: 2003 Capítulos 9 e 10 TCC-00.254 Desafios de Programação

3

Bibliotecas Nativas

Sério!? Você quer uma biblioteca nativa? Esqueça!

TCC-00.254 Desafios de Programação

4

2

09/06/2015

Grafos – Parte 1

Estruturas de Dados

TCC-00.254 Desafios de Programação

5

Tipos de Grafos

= =

• • • • •

vértices (ou nós) e

, =

arestas (ou arcos)

Direcionado / Não direcionado Com pesos / Sem pesos

arestas arestas e/ou vértices

Cíclico / Acíclico

arestas

Simples / Não simples

arestas

Implícito / Explícito

arestas e/ou vértices

TCC-00.254 Desafios de Programação

6

3

09/06/2015

Exemplo 1

2

4 Direcionado / Não direcionado Com pesos / Sem pesos Cíclico / Acíclico Simples / Não simples Implícito / Explícito (depende)

3 6

5

= 1, 2, 3, 4, 5, 6 = 1,3 , 2,1 , 3,1 , 3,2 , 4,2 , 4,4 , 5,6 TCC-00.254 Desafios de Programação

7

Matriz de Adjacências Representação Explícita 1

2

4 Para

3 1

De

3

4

5

6

1

1

6

5

2

2

1

3

1

4 5

1 1

1 1

6

TCC-00.254 Desafios de Programação

8

4

09/06/2015

Listas de Adjacências Representação Explícita 1

2

4 Para

3 6 De 5

1

3

2

1

3

1

2

4

2

4

5

6

6

TCC-00.254 Desafios de Programação

9

Exemplo de Estrutura Representação Explícita struct edge_s { int v; float weight; }; struct graph_s { edge_s edges[MAX_NVERTICES][MAX_DEGREE]; int degree[MAX_NVERTICES]; float weight[MAX_NVERTICES]; int nvertices; int nedges; };

TCC-00.254 Desafios de Programação

10

5

09/06/2015

Grafos – Parte 1

Travessia

TCC-00.254 Desafios de Programação

11

Travessia



Visitar cada vértice e cada aresta uma única vez e em uma ordem pré-definida



Requer controle de vértices descobertos e vértices processados



Tipos de travessia: Largura Profundidade

TCC-00.254 Desafios de Programação

12

6

09/06/2015

Travessia em Largura Pseudocódigo BFS(G, s) initialize status, parent, and distance arrays; initialize queue Q; Enqueue(Q, s) status[s] = DISCOVERED; while (Q not empty) do u = Dequeue(Q); process vertex u; status[u] = PROCESSED; for each v adjacent to u do if ({u, v} is a valid edge) then process edge {u, v}; if (status[v] == UNDISCOVERED) then Enqueue(Q, v); status[v] = DISCOVERED; Aplicações distance[v] = distance[u] + 1; parent[v] = u; • Encontrar caminhos end if end if • Calcular caminho end for mais curto end while (requer modificações) end TCC-00.254 Desafios de Programação

13

Travessia em Profundidade Pseudocódigo não Recursivo DFS(G, s) initialize status, parent and depth arrays; initialize stack S; Push(S, s) status[s] = DISCOVERED; while (S not empty) do u = Pop(S); process vertex u; status[u] = PROCESSED; for each v adjacent to u do if ({u, v} is a valid edge) then process edge {u, v}; if (status[v] == UNDISCOVERED) then Push(S, v); status[v] = DISCOVERED; Aplicações depth[v] = depth[u] + 1; parent[v] = u; • Determinar ciclos em end if grafos não direcionados end if end for • Identificar componentes end while conexos end TCC-00.254 Desafios de Programação

14

7

09/06/2015

Grafos – Parte 1

Ordenação Topológica

TCC-00.254 Desafios de Programação

15

Ordenação Topológica

• •

Aplicada sobre grafos direcionados acíclicos



Aplicado em

Ordena vértices de modo que todas as arestas sigam o “mesmo sentido” Definição de precedência (agendamento) Determinar caminho mais curto Determinar caminho mais longo

TCC-00.254 Desafios de Programação

16

8

09/06/2015

Ordenação Topológica Pseudocódigo não Recursivo TopSort(G) initialize indegree, and sorted arrays; initialize queue Q; for each v in G do if (indegree[v] == 0) then, Enqueue(Q, v) end for count = 0; while (Q not empty) do x = Dequeue(Q); sorted[count] = x; for each y adjacent to x do indegree[y]--; if (indegree[y] == 0) then, Enqueue(Q, y) end for count++; end while assert count equals number of vertices; end TCC-00.254 Desafios de Programação

17

TCC-00.254 Desafios de Programação

18

Grafos – Parte 2

Ciclos

9

09/06/2015

Ciclos • •

Grafos conexos que não são árvores contém ciclos Caminho Euleriano visita exatamente uma vez cada arestas Vértices podem ser visitados mais de uma vez Caminho: Não precisa começar e terminar no mesmo vértice Circuito: Começa e termina no mesmo vértice Algoritmo: Fleury (muito grande para um slide)



Caminho Hamiltoniano visita exatamente uma vez cada vértice Por dualidade, caminho Euleriano reduz para caminho Hamiltoniano O problema do caixeiro viajante consiste em encontrar o caminho Hamiltonian mais curto (NP-difícil) Algoritmo: Em grafos pequenos, backtracking

TCC-00.254 Desafios de Programação

19

Grafos – Parte 2

Árvore Geradora Mínima

TCC-00.254 Desafios de Programação

20

10

09/06/2015

Árvore Geradora Mínima



Uma árvore geradora de um grafo = , é um subconjunto de arestas de formando uma árvore que conecta todos os vértices de



Uma árvore geradora mínima é a árvore geradora onde a soma do peso das arestas é a menor possível



Algoritmos Prim e Kruskal

Aplicações • Conectar cidades com menor distância de rodovias • Provar conectividade (não precisa ser árvore mínima) TCC-00.254 Desafios de Programação

21

Algoritmo de Prim Pseudocódigo Prim(G, start) initialize intree, distance, and parent arrays; v = start; distance[start] = 0; while (intree[v] == FALSE) intree[v] = TRUE; for each w adjacent to weight = weight of if ((distance[w] >

do v do edge {v, w}; weight) and (intree[w] == FALSE)) then

parent[w] = v; distance[w] = weight; end if end for v = vertex not in tree, and min. distance end while end TCC-00.254 Desafios de Programação

22

11

09/06/2015

Variações de Árvore Geradora Mínima



Árvore Geradora Máxima Utilize pesos negativos Aplicação: contratos públicos fraudulentos



Árvore Geradora de Produto Mínimo log

= log

+ log

Aplicação: Não sei. Mas a Maratona é criativa.

TCC-00.254 Desafios de Programação

23

Grafos – Parte 2

Caminho Mais Curto

TCC-00.254 Desafios de Programação

24

12

09/06/2015

Caminho Mais Curto



Grafo sem pesos Travessia em largura resolve



Grafo com pesos positivos Dijkstra – retorna o menor caminho entre um dado vértice de e qualquer outro vértice de Floyd-Warshall – retorna o comprimento do menor caminho entre quaisquer dois vértices de , mas não os caminhos

TCC-00.254 Desafios de Programação

25

Algoritmo de Dijkstra Pseudocódigo Dijkstra(G, start) initialize intree, distance, and parent arrays; v = start; distance[start] = 0; while (intree[v] == FALSE) do intree[v] = TRUE; for each w adjacent to v do weight = weight of edge {v, w}; if (distance[w] > distance[v] + weight) then distance[w] = distance[v] + weight; parent[w] = v; end if end for v = vertex not in tree, and min. distance end while end

TCC-00.254 Desafios de Programação

26

13

09/06/2015

Algoritmo de Floyd-Warshall Pseudocódigo FloydWarshall(G) for each vertex k in G do for each vertex i in G do for each vertex j in G do if (G[i,k] + G[k,j] < G[i,j]) then G[i,j] = G[i,k] + G[k,j]; end if end for end for end for end

TCC-00.254 Desafios de Programação

27

Grafos – Parte 2

Fluxo de Rede

TCC-00.254 Desafios de Programação

28

14

09/06/2015

Problema do Fluxo Máximo



Em um grafo orientado = , , onde cada aresta , ∈ possui capacidade , > 0, calcular o fluxo máximo suportado pela



Aplicações

Grafo Bipartido

O problema em si é interessante Grafo bipartido (bigrafo)



Algoritmo Vários! Ford-Fulkerson (mais simples de implementar) TCC-00.254 Desafios de Programação

29

Algoritmo de Ford-Fulkerson Pseudocódigo FordFulkerson(G, source, sink) max_flow = 0; while (BFS(G, source, sink, parent)) do path_flow = MAX_VALUE; for each v in the path from skin to source do u = parent[v] path_flow = min(path_flow, G[u,v]); end for for each v in the path from sink to source do u = parent[v]; G[u,v] -= path_flow; G[v,u] += path_flow; end for max_flow += path_flow; end while end TCC-00.254 Desafios de Programação

30

15