CIC 110 Análise e Projeto de Algoritmos I

Documentos relacionados
Aula 09. Percurso em grafo

Algoritmos em Grafos: Caminho Mínimo

CIC 110 Análise e Projeto de Algoritmos I

Prova Didática Grafos: Árvores Geradoras e Caminhos Mínimos, Análise de Complexidade

CIC 111 Análise e Projeto de Algoritmos II

Caminho Mínimo de Fonte Única em Grafos sem Pesos Negativos

Grafos: caminhos mínimos

Distâncias Mínimas. Pedro Ribeiro 2014/2015 DCC/FCUP. Pedro Ribeiro (DCC/FCUP) Distâncias Mínimas 2014/ / 27

Problema do Caminho Mínimo

Grafos. Notas. Notas. Notas. Notas. Caminhos mais curtos de única origem. Subestrutura ótima. Propriedades de caminhos mais curtos

06 Grafos: Caminhos Mínimos SCC0503 Algoritmos e Estruturas de Dados II

GRAFOS Aula 07 Algoritmos de Caminho Mínimo: Bellman-Ford / Floyd-Warshall Max Pereira

CIC 111 Análise e Projeto de Algoritmos II

Teoria dos Grafos Aula 22

Otimização em Grafos

Grafos Caminhos mais Curtos

Caminhos mínimos de única origem

Grafos - Introdução. Pedro Ribeiro 2014/2015 DCC/FCUP. Pedro Ribeiro (DCC/FCUP) Grafos - Introdução 2014/ / 32

Teoria dos Grafos Aula 24

Algoritmos e Estruturas de Dados II

O estudo utilizando apenas este material não é suficiente para o entendimento do conteúdo. Recomendamos a leitura das referências no final deste

Árvore Geradora Mínima

Eduardo Camponogara. DAS-9003: Introdução a Algoritmos

Aula 08. Estruturas de dados Árvore e Grafo

Acessibilidade e Fecho Transitivo de Grafos Dirigidos

Universidade Federal de Alfenas

CIC 111 Análise e Projeto de Algoritmos II

5COP096 TeoriadaComputação

Caminho Mínimo de Fonte Única em Grafos com Pesos Negativos Letícia Rodrigues Bueno

INF 1010 Estruturas de Dados Avançadas

Complexidade de Algoritmos

INF 1010 Estruturas de Dados Avançadas

CIC 110 Análise e Projeto de Algoritmos I

Distâncias entre vértces em um grafo. Implementação sequencial

SCC Laboratório de Algoritmos Avançados. Multigrafos: Caminhos Mínimos. Multigrafos e Multidígrafos. Multigrafos e Multidígrafos

AED2 - Aula 22 Busca em largura, cálculo de distâncias

Grafos. Notas. Notas. Notas. Notas. Caminhos mais curtos de todos os pares

Algoritmo de Dijkstra (um para todos ; arestas de peso não negativo ; guloso)

Algoritmo Floyd-Warshall. Problema dos caminhos mínimos entre todos os pares. Programação dinâmica

Caminhos mínimos de todos os pares

Grafos Parte 1. Aleardo Manacero Jr.

Grafos - Representação

Desafios de Programação TCC Turma A-1

CIC 110 Análise e Projeto de Algoritmos I

MAC328 Algoritmos em grafos (4/6/2004) Caminhos mínimos

Algoritmo de Dijkstra Estudo e Implementação

Algoritmo de Dijkstra Wikipédia, a enciclopédia livre

Teoria dos Grafos Aula 23

CIC 110 Análise e Projeto de Algoritmos I

GRAFOS BUSCAS E MENOR CAMINHO. Prof. André Backes

INF 1010 Estruturas de Dados Avançadas

Processamento da Informação Números Aleatórios Matrizes parte 2

AULA 13 PROJETO E ANÁLISE DE ALGORITMOS. Problema do caminho mais curto de uma única origem em grafos Karina Valdivia Delgado

Tecnicas Essencias Greedy e Dynamic

Algoritmos em Grafos

Teoria dos Grafos. Valeriano A. de Oliveira, Socorro Rangel, Silvio A. de Araujo. Departamento de Matemática Aplicada

Problema do Caminho Mais Curto. Problema do Caminho Mais Curto

ESTRUTURAS DE DADOS. prof. Alexandre César Muniz de Oliveira. 1. Introdução 2. Pilhas 3. Filas 4. Listas 5. Árvores 6. Ordenação 7. Busca 8.

CIC 110 Análise e Projeto de Algoritmos I

QUESTÕES DE PROVAS ANTIGAS

Teoria dos Grafos Aula 8

Sub-grafo. Árvore Geradora Mínima

grafo nós vértices arcos arestas

CIC 111 Análise e Projeto de Algoritmos II

UNIVERSIDADE DE SÃO PAULO INSTITUTO DE CIÊNCIAS MATEMÁTICAS E DE COMPUTAÇÃO Departamento de Ciências de Computação

Complexidade de algoritmos Notação Big-O

Grafos - Aplicação. Implemente na linguagem C a função procurarcaminho(...).

Ordenação: HeapSort. Prof. Túlio Toffolo BCC202 Aula 17 Algoritmos e Estruturas de Dados I

Grafos: árvores geradoras mínimas. Graça Nunes

CIC 110 Análise e Projeto de Algoritmos I

Teoria dos Grafos Aula 6

Grafos: Busca. SCE-183 Algoritmos e Estruturas de Dados 2. Thiago A. S. Pardo Maria Cristina

Análise de Complexidade de Algoritmos. mario alexandre gazziro

Caminho mais curto. 1 - Caminho não pesado

Eduardo Camponogara. DAS-9003: Introdução a Algoritmos

PCC173 - Otimização em Redes

Projeto e Análise de Algoritmos. Método Guloso

Estruturas de Dados Grafos

Grafos: caminhos (matriz adjacência)

Análise e Síntese de Algoritmos

O estudo utilizando apenas este material não é suficiente para o entendimento do conteúdo. Recomendamos a leitura das referências no final deste

03 Grafos: percurso, ponderação e caminhos SCC0503 Algoritmos e Estruturas de Dados II

AULA 11 PROJETO E ANÁLISE DE ALGORITMOS. Conceitos básicos e representação de grafos Karina Valdivia Delgado

Grafos. Exemplo de árvore geradora mínima. Notas. Notas. Notas. Notas. Árvores espalhadas mínimas. Como construir uma árvore geradora miníma

Grafos Caminhos mais curtos

Protocolos de Roteamento link-state

UNIVERSIDADE DE SÃO PAULO INSTITUTO DE CIÊNCIAS MATEMÁTICAS E DE COMPUTAÇÃO Departamento de Ciências de Computação

Grafos: Busca. Algoritmos e Estruturas de Dados 2. Graça Nunes

1 Distância em Grafos

Aula 13: Ordenação - Heapsort. Bruno Hott Algoritmos e Estruturas de Dados I DECSI UFOP

Grafos tipo abstrato de dados

CIC 110 Análise e Projeto de Algoritmos I

Grafos COM11087-Tópicos Especiais em Programação II

Busca em largura. Algoritmos em Grafos. Marco A L Barbosa

Grafos: algoritmos de busca

Busca em Largura. Adaptado de Humberto C. B. Oliveira

ESTRUTURA DE DADOS E ALGORITMOS HEAPS E LISTAS DE PRIORIDADES

Marcelo Keese Albertini Faculdade de Computação Universidade Federal de Uberlândia

Estudo e implementação de heurísticas para determinação do caminho de menor custo para atender a rotas pré estabelecidas. Por: Charles Pereira

Transcrição:

CIC 0 Análise e Projeto de Algoritmos I Prof. Roberto Affonso da Costa Junior Universidade Federal de Itajubá

AULA Caminhos mais curtos

Caminhos mais curtos Encontrar um caminho mais curto entre dois nós de um grafo é um problema importante que possui muitas aplicações práticas. Por exemplo, um problema natural relacionado a uma rede rodoviária é calcular o comprimento mais curto possível de uma rota entre duas cidades, dado o comprimento das estradas. Em um grafo não ponderado, o comprimento de um caminho é igual ao número de suas arestas, e podemos simplesmente usar uma busca de largura para encontrar um caminho mais curto. No entanto, em grafos com pesos os algoritmos mais sofisticados são necessários para encontrar os caminhos mais curtos.

Algoritmo Bellman-Ford O algoritmo Bellman-Ford encontra os caminhos mais curtos de um nó inicial para todos os nós do grafo. O algoritmo pode processar todos os tipos de grafos, desde que o grafo não contenha um ciclo com comprimento negativo. Se o grafo contiver um ciclo negativo, o algoritmo pode detectar isso. O algoritmo controla as distâncias do nó inicial para todos os nós do grafo. Inicialmente, a distância para o nó inicial é 0 e a distância para todos os outros nós é infinito. O algoritmo reduz as distâncias ao encontrar arestas que encurtam os caminhos até que não seja possível reduzir qualquer distância.

Exemplo Consideremos como o algoritmo Bellman-Ford funciona no seguinte grafo: 0 7 4 -

Exemplo Cada nó do grafo é atribuído a uma distância. Inicialmente, a distância para o nó inicial é 0 e a distância para todos os outros nós é infinita. O algoritmo busca a aresta que reduzam as distâncias. Primeiro, todas as bordas do nó reduzem as distâncias: 0 7 4-7

Exemplo Depois disso, as arestas e 4 reduzem as distâncias: 0 7 7 4 -

Exemplo Finalmente, há mais uma mudança: 0 7 4 -

Exemplo Depois disso, nenhuma aresta pode reduzir qualquer distância. Isso significa que as distâncias são finais, e nós calculamos com sucesso as distâncias mais curtas do nó inicial para todos os nós do grafo. Por exemplo, a distância mais curta do nó ao nó corresponde ao seguinte caminho: 0 7 4 -

Implementação A seguinte implementação do algoritmo Bellman- Ford determina as distâncias mais curtas de um nó x para todos os nós do grafo. O código assume que o grafo é armazenado como arestas da lista de aresta que consiste em tuplas do formulário (a, b, w), o que significa que há uma aresta do nó a para o nó b com peso w. O algoritmo consiste em n- rodadas, e em cada rodada o algoritmo passa por todas as arestas do grafo e tenta reduzir as distâncias. O algoritmo constrói uma distância de matriz que irá conter as distâncias de x para todos os nós do grafo. O INF constante denota uma distância infinita.

Implementação for (int i = ; i <= n; i++) distance[i] = INF; distance[x] = 0; for (int i = ; i <= n-; i++) { for (auto e : edges) { int a, b, w; tie(a, b, w) = e; distance[b] = min(distance[b], distance[a]+w); } }

Implementação A complexidade do tempo do algoritmo é O(nm), porque o algoritmo consiste em n- rodadas e itera através de todas as m arestas durante uma rodada. Se não houver ciclos negativos no grafo, todas as distâncias são finais após n - rodadas, pois cada caminho mais curto pode conter no máximo n - bordas. Na prática, as distâncias finais geralmente podem ser encontradas mais rapidamente do que em n - rodadas. Assim, uma maneira possível de tornar o algoritmo mais eficiente é parar o algoritmo se nenhuma distância pode ser reduzida durante uma rodada.

Ciclos Negativos O algoritmo Bellman-Ford também pode ser usado para verificar se o grafo contém um ciclo com comprimento negativo. Por exemplo, o grafo 4-7

Ciclos Negativos contém um ciclo negativo 4 com comprimento 4. Se o grafo contiver um ciclo negativo, podemos encurtar infinitamente muitas vezes qualquer caminho que contenha o ciclo repetindo o ciclo uma e outra vez. Assim, o conceito de um caminho mais curto não é significativo nessa situação. Um ciclo negativo pode ser detectado usando o algoritmo Bellman-Ford executando o algoritmo para n rodadas. Se a última rodada reduzir qualquer distância, o grafo contém um ciclo negativo. Observe que esse algoritmo pode ser usado para procurar um ciclo negativo em todo o grafo, independentemente do nó inicial.

Algoritmo SPFA O algoritmo SPFA ("Shortest Path Faster Algorithm") é uma variante do algoritmo Bellman- Ford, que muitas vezes é mais eficiente do que o algoritmo original. O algoritmo SPFA não passa por todas as arestas em cada rodada, mas, em vez disso, escolhe as arestas para serem examinadas de forma mais inteligente. O algoritmo mantém uma fila de nós que podem ser usados para reduzir as distâncias. Primeiro, o algoritmo adiciona o nó inicial x à fila. Então, o algoritmo sempre processa o primeiro nó na fila, e quando uma vantagem a b reduz uma distância, o nó b é adicionado à fila.

Algoritmo SPFA A eficiência do algoritmo SPFA depende da estrutura do grafo: o algoritmo é frequentemente eficiente, mas a maior complexidade do tempo é ainda O(nm) e é possível criar entradas que tornem o algoritmo tão lento quanto o original Algoritmo Bellman-Ford.

Algoritmo Dijkstra O algoritmo Dijkstra encontra os caminhos mais curtos do nó inicial para todos os nós do gráfico, como o algoritmo Bellman-Ford. O benefício do algoritmo Dijsktra é que ele é mais eficiente e pode ser usado para processar grandes grafos. No entanto, o algoritmo exige que não existam arestas de peso negativas no grafo. Como o algoritmo Bellman-Ford, o algoritmo Dijkstra mantém distâncias nos nós e os reduz durante a pesquisa. O algoritmo Dijkstra é eficiente, porque ele só processa cada aresta no grafo uma vez, usando o fato de que não há arestas negativas.

Exemplo Consideremos o grafo a seguir quando o nó inicial é o nó : 0 6 9 4 Como no algoritmo Bellman-Ford, inicialmente a distância para o nó inicial é 0 e a distância para todos os outros nós é infinita.

Exemplo Em cada etapa, o algoritmo Dijkstra seleciona um nó que ainda não foi processado e cuja distância é a menor possível. O primeiro tal nó é nó com distância 0. Quando um nó é selecionado, o algoritmo passa por todas as arestas que começam no nó e reduz as distâncias usando-os: 0 6 6 9 4

Exemplo Nesse caso, as arestas do nó reduziram as distâncias dos nós e 4, cujas distâncias são agora de 6 e. O próximo nó a ser processado é o nó 4 com a distância. Isso reduz a distância para o nó de 7: 0 6 6 9 4 7

Exemplo Depois disso, o próximo nó é o nó, que reduz a distância ao nó a 8: 0 6 6 9 8 4 7

Exemplo Uma propriedade notável no algoritmo Dijkstra é que sempre que um nó é selecionado, sua distância é final. Por exemplo, neste ponto do algoritmo, as distâncias 0, e 7 são as distâncias finais para os nós, 4 e. Depois disso, o algoritmo processa os dois nós remanescentes e as distâncias finais são as seguintes: 0 6 6 9 8 4 7

Bordas Negativas A eficiência do algoritmo Dijkstra baseia-se no fato de que o grafo não contém arestas negativas. Se houver uma aresta negativa, o algoritmo pode dar resultados incorretos. Como exemplo, considere o seguinte grafo: 4 6 -

Bordas Negativas O caminho mais curto do nó para o nó 4 é 4 e seu comprimento é. No entanto, o algoritmo Dijkstra encontra o caminho 4 seguindo as bordas do peso mínimo. O algoritmo não leva em consideração que, no outro caminho, o peso - compensa o peso anterior 6. 4 6 -

Implementação A seguinte implementação do algoritmo Dijkstra calcula as distâncias mínimas de um nó x para outros nós do grafo. O grafo é armazenado como listas de adjacência de modo que adj[a] contenha um par(b, w) sempre quando houver uma aresta do nó a para o nó b com peso w. Uma implementação eficiente do algoritmo Dijkstra exige que seja possível encontrar eficientemente o nó de distância mínima que não tenha sido processado. Uma estrutura de dado apropriada para isso é uma fila de prioridade que contém os nós ordenados por suas distâncias. Usando uma fila de prioridade, o próximo nó a ser processado pode ser recuperado em tempo logarítmico.

Implementação No código a seguir, a fila de prioridade q contém pares da forma (-d, x), o que significa que a distância atual para o nó x é d. A distância do vetor contém a distância para cada nó e o vetor processado indica se um nó foi processado. Inicialmente, a distância é 0 a x e a todos os outros nós.

Implementação for (int i = ; i <= n; i++) distance[i] = INF; distance[x] = 0; q.push({0,x}); while (!q.empty()) { int a = q.top().second; q.pop(); if (processed[a]) continue; processed[a] = true; for (auto u : adj[a]) { int b = u.first, w = u.second; if (distance[a]+w < distance[b]) { distance[b] = distance[a]+w; q.push({-distance[b],b}); } } }

Implementação Observe que a fila de prioridade contém distâncias negativas para nós. O motivo para isso é que a versão padrão da fila de prioridade C++ encontra elementos máximos, enquanto queremos encontrar elementos mínimos. Ao usar distâncias negativas, podemos usar diretamente a fila de prioridade padrão. Observe também que pode haver várias instâncias do mesmo nó na fila de prioridade; no entanto, apenas a instância com a distância mínima será processada. A complexidade do tempo da implementação acima é O(n + m log m), porque o algoritmo passa por todos os nós do grafo e adiciona para cada aresta uma distância máxima para a fila de prioridade.

Algoritmo Floyd-Warshall O algoritmo Floyd-Warshall fornece uma maneira alternativa de abordar o problema de encontrar caminhos mais curtos. Ao contrário dos outros algoritmos, ele encontra todos os caminhos mais curtos entre os nós em uma única execução. O algoritmo mantém uma matriz bidimensional que contém distâncias entre os nós. Primeiro, as distâncias são calculadas apenas usando arestas diretas entre os nós e, depois disso, o algoritmo reduz distâncias usando nós intermediários em caminhos.

Exemplo Considere o seguinte grafo: 6 4 9

Exemplo Inicialmente, a distância de cada nó para si é 0 e a distância entre os nós a e b é x se houver uma aresta entre os nós a e b com o peso x. Todas as outras distâncias são infinitas. No grafo anterior, a matriz inicial é a seguinte: 4 0 6 6 0 9 0 4 0 9 0

Exemplo O algoritmo consiste em rodadas consecutivas. Em cada rodada, o algoritmo seleciona um novo nó que pode atuar como um nó intermediário nos caminhos de agora em diante e as distâncias são reduzidas usando este nó. Na primeira rodada, o nó é o novo nó intermediário. Existe um novo caminho entre os nós e com o comprimento 8, porque o nó os conecta. Há também um novo caminho entre os nós e com o comprimento.

Exemplo 4 0 6 8 6 0 9 8 0 4 0 9 0

Exemplo Na segunda rodada, o nó é o novo nó intermediário. Isso cria novos caminhos entre os nós 4 e e entre os nós 4 e : 4 0 6 8 6 0 4 9 8 0 6 4 4 6 0 9 0

Exemplo Na terceira rodada, o nó é a nova rodada intermediária. Existe um novo caminho entre os nós e 4: 4 0 6 8 6 0 9 9 8 0 6 4 9 6 0 9 0

Exemplo O algoritmo continua assim, até que todos os nós tenham sido nomeados nós intermediários. Após o algoritmo ter terminado, a matriz contém as distâncias mínimas entre os dois nós: 4 0 6 8 7 6 0 8 8 0 6 4 8 6 0 7 0

Exemplo Por exemplo, a matriz nos diz que a distância mais curta entre os nós e 4 é 8. Isso corresponde ao seguinte caminho: 6 4 9

Implementação A vantagem do algoritmo Floyd-Warshall de que é fácil de implementar. O código a seguir constrói uma matriz de distância onde distance[a][b] é a menor distância entre os nós a e b. Primeiro, o algoritmo inicializa a distância usando a matriz de adjacência adj do grafo: for (int i = ; i <= n; i++) { for (int j = ; j <= n; j++) { if (i == j) distance[i][j] = 0; else if (adj[i][j]) distance[i][j] = adj[i][j]; else distance[i][j] = INF; } }

Implementação Depois disso, as distâncias mais curtas podem ser encontradas da seguinte forma: for (int k = ; k <= n; k++) { for (int i = ; i <= n; i++) { for (int j = ; j <= n; j++) { distance[i][j] = min(distance[i][j],distance[i][k]+distance[k][j]); } } }

Implementação A complexidade do tempo do algoritmo é O(n ), porque contém três loops aninhados que atravessam os nós do grafo. Uma vez que a implementação do algoritmo Floyd- Warshall é simples, o algoritmo pode ser uma boa opção, mesmo que seja necessário apenas encontrar um único caminho mais curto no grafo. No entanto, o algoritmo só pode ser usado quando o grafo é tão pequeno que uma complexidade de tempo cúbico é suficientemente rápida.

Exercício Você pode fazer eles no no codepit.io CIC 0 9 senha: unifei