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