Nos últimos artigos dedicámo-nos a grafos simples, mas existem muitas variações ao conceito base de grafo. Alguns exemplos do que é possível incluem: grafos com múltiplas arestas entre nós; grafos com arestas de um nó para ele próprio; grafos com cores nos nós e/ou nas arestas; grafos com pesos nos nós e/ou nas arestas; qualquer combinação dos anteriores.

O foco deste artigo são grafos pesados, ou seja, grafos em que cada aresta tem um valor ou peso associado. O propósito deste peso é de representar vários casos importantes, por exemplo, distâncias entre nós. Como devem imaginar, este tipo de situações é muito frequente e por isso tem uma conjunto de algoritmos próprio, alguns dos quais iremos estudar neste artigo.

Iremos ver vários algoritmos para três classes de problemas, com vantagens e aplicações em situações diferentes. Opcionalmente, incluímos alguns tópicos extra por problema para consolidarem o que sabem e verem outras aplicações.

Distâncias de uma fonte única

O primeiro problema que iremos ver é o problema do caminho mais curto de fonte única. O objetivo é calcular o caminho mais curto que começa num dado nó, para todos os outros nós.

Iremos ver um conjunto de algoritmos que se aplicam a este problema e que têm restrições diferentes.

Algoritmo de Dijsktra

O primeiro algoritmo é dos algoritmos mais conhecidos de grafos. Chama-se algoritmo de Dijsktra e funciona da seguinte forma:

Artigo: Capítulo 4.5 do livro Competitive Programming I

Ler das páginas 74 a 75 do livro.

Nota: Para quem não tem o livro

É normal que muitos não tenham uma cópia do livro. Felizmente a primeira edição do livro está disponível de graça neste link, a página 74 à 75 (ou da 86 à 87 do PDF).

Algoritmo de Bellman-Ford

O segundo algoritmo é útil para ser aplicado a grafos em que nem todas as arestas têm pesos positivos, uma falha do algoritmo de DIjsktra. Veremos como funciona:

Artigo: Capítulo 4.6 do livro Competitive Programming I

Ler das páginas 75 a 77 do livro (ou 87 a 89 do PDF).

* Extras

Se quiserem saber um pouco mais sobre este tipo de coisa, um conceito muito interessante e que permite tirar muitas ideias sobre a estrutura dos caminhos mais curtos é o da "árvore de caminhos/distâncias mais curtas". Normalmente não é preciso calculá-lo explicitamente, pode-se usar apenas o que resulta da aplicação de um dos algoritmos acima. É um conceito um pouco mais avançado e é por isso que é opcional.

Artigo: Árvores de distâncias mais curtas

Um artigo interessante sobre o assunto.

Distâncias de múltiplas fontes

Já vimos como calcular as distâncias a partir de um nó, mas outro conceito importante é calcular distâncias entre todos os pares de nós. Veremos um algoritmo que faz exatamente isso.

Algoritmo de Floyd-Warshall

Este algoritmo é o mais conhecido e o mais eficiente que se conhece para o problema geral de calcular o caminho mais curto entre todos os pares de vértices. Vejamos como funciona:

Artigo: Capítulo 4.7 do livro Competitive Programming I

Ler das páginas 77 a 79 do livro (ou 89 a 91 do PDF).

* Extras

Além do problema base a que se destina, o algoritmo de *Floyd-Warshall" é muito versátil e por isso aplica-se a algumas variações do problema de distâncias. Vejamos alguns exemplos:

Artigo: Capítulo 4.7 do livro Competitive Programming I

Ler das páginas 79 a 80 do livro (ou 91 a 92 do PDF).

Árvores de suporte de custo mínimo

O último problema que iremos ver é o determinar a árvore de suporte de custo mínimo de um grafo. Uma árvore de suporte de um grafo é um subgrafo que é uma árvore e que inclui todos os vértices do grafo original. Como o nome indica, a árvore de suporte de custo mínimo é a árvore de suporte cuja soma dos pesos das arestas é minimizada. Isto tem vários paralelos interessantes para situações práticas e é por isso útil em diferentes problemas, como iremos ver.

Algoritmo de Prim

O primeiro algoritmo que iremos ver é o algoritmo de Prim. Sem mais demoras aqui está ele:

Artigo: Minimum spanning tree do GeeksforGeeks

Um artigo da GeeksforGeeks que descreve o algoritmo de Prim em detalhe (e com código).

Algoritmo de Kruskal

Finalmente vamos ver um algoritmo que é mais simples de implementar e que por isso é normalmente o mais usado em concursos de programação. Porém, necessita de uma estrutura de dados que apesar de simples não é trivial, nomeadamente o union-find. Esta estrutura será abordada noutro artigo, mas faremos-lhe uma breve introdução aqui também. Ai está, então, o algoritmo:

Artigo: Capítulo 4.4 do livro Competitive Programming I

Ler das páginas 70 a 71 do livro (ou 82 a 83 do PDF).

* Extras

Existem algumas variações interessantes do problema. É curioso como os algoritmos base que vimos se aplicam tão bem (ou seja, sem mudar quase nada) a vários desses problemas que à primeira vista não pareciam possuir o mesmo tipo de propriedade greedy. Vejamos alguns deles:

Artigo: Capítulo 4.4 do livro Competitive Programming I

Ler das páginas 71 a 73 do livro (ou 83 a 85 do PDF).

Aplicações

Para terminar bem, vamos a um problema para cada uma dos três problemas:

Problema 1: Get Shorty

Problema do Kattis, getshorty - Get Shorty

Problema 2: Fire Station

Problema do Kattis, firestation - Fire Station

Problema 3: Minimum Spanning Tree

Problema do Kattis, minspantree - Minimum Spanning Tree

E mais dois extras, um para aplicar o Bellman-Ford e outro para juntar várias ideias de grafos:

*Problema 4: Robot Control

Problema D da ronda 201 (Div. 1) do CodeForces - Robot Control

*Problema 5: Breaking Good

Problema E da ronda 287 (Div. 2) do CodeForces - Breaking Good

Conclusão

Para consolidar todos os tópicos anteriores, aqui estão um conjunto de artigos extra que podem ser interessantes:

*Artigo: Caminhos em grafos pesados do TopCoder

Um artigo sobre o tema que tem uma maior incidência na implementação.

*Artigo: Slides de distâncias mínimas

Um conjunto de slides que contém todos estes conceitos acompanhados de mais exemplos e melhores imagens.

*Artigo: Slides de árvores de suporte de custo mínimo

Um conjunto de slides que contém todos estes conceitos acompanhados de mais exemplos e melhores imagens.