Desafios de Programação TCC-00.254 Turma A-1 Conteúdo Grafos Professor Leandro Augusto Frata Fernandes laffernandes@ic.uff.br 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
Leitura Sugerida Art of Programming Contest AREFIN, A. S. 2 nd 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
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 Cíclico / Acíclico Simples / Não simples Implícito / Explícito arestas arestas e/ou vértices arestas arestas arestas e/ou vértices TCC-00.254 Desafios de Programação 6 3
Exemplo 1 2 4 3 6 Direcionado / Não direcionado Com pesos / Sem pesos Cíclico / Acíclico Simples / Não simples Implícito / Explícito (depende) 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 3 Para 1 2 3 4 5 6 5 6 De 1 1 2 1 3 1 1 4 1 1 5 1 6 TCC-00.254 Desafios de Programação 8 4
Listas de Adjacências Representação Explícita 1 2 4 3 Para 1 3 5 6 De 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
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
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; distance[v] = distance[u] + 1; end parent[v] = u; end if end if end while Aplicações Encontrar caminhos Calcular caminho mais curto (requer modificações) 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; depth[v] = depth[u] + 1; end parent[v] = u; end if end if end while Aplicações Determinar ciclos em grafos não direcionados Identificar componentes conexos TCC-00.254 Desafios de Programação 14 7
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 Ordena vértices de modo que todas as arestas sigam o mesmo sentido Aplicado em Definição de precedência (agendamento) Determinar caminho mais curto Determinar caminho mais longo TCC-00.254 Desafios de Programação 16 8
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) 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) count++; end while end assert count equals number of vertices; TCC-00.254 Desafios de Programação 17 Grafos Parte 2 Ciclos TCC-00.254 Desafios de Programação 18 9
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
Á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) end 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] > weight) and (intree[w] == FALSE)) then parent[w] = v; distance[w] = weight; end if v = vertex not in tree, and min. distance end while TCC-00.254 Desafios de Programação 22 11
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
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) end 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 v = vertex not in tree, and min. distance end while TCC-00.254 Desafios de Programação 26 13
Algoritmo de Floyd-Warshall Pseudocódigo FloydWarshall(G) end 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 TCC-00.254 Desafios de Programação 27 Grafos Parte 2 Fluxo de Rede TCC-00.254 Desafios de Programação 28 14
Problema do Fluxo Máximo Em um grafo orientado =,, onde cada aresta, possui capacidade, >0, calcular o fluxo máximo suportado pela Aplicações O problema em si é interessante Grafo bipartido (bigrafo) Algoritmo Vários! Ford-Fulkerson (mais simples de implementar) Grafo Bipartido TCC-00.254 Desafios de Programação 29 Algoritmo de Ford-Fulkerson Pseudocódigo FordFulkerson(G, source, sink) end 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]); for each v in the path from sink to source do u = parent[v]; G[u,v] -= path_flow; G[v,u] += path_flow; max_flow += path_flow; end while TCC-00.254 Desafios de Programação 30 15