Programação competitiva · Menor caminho ponderado
Não queremos menos passos. Queremos menor custo.
Dijkstra mantém a melhor distância conhecida até cada vértice e sempre escolhe, entre os candidatos, aquele com o menor custo acumulado.
Dijkstra
Fila de prioridade
Relaxamento
heapq
Pesos não negativos
01
Qual problema vamos resolver?
Usando o mesmo grafo da aula anterior, queremos sair de A e chegar em G pagando o menor custo possível.
Origem
A
A distância de A para ele mesmo começa em 0.
Destino
G
Queremos descobrir o menor custo acumulado até G.
Pesos
Diferentes
Cada aresta possui seu próprio custo.
02
A ideia do Dijkstra
O algoritmo repete três ideias simples:
Pegue o menor custo disponível
→
Examine seus vizinhos
→
Tente melhorar as distâncias
→
Repita
A expressão “tentar melhorar a distância” recebe um nome importante:
relaxamento da aresta.
Não é DFS
DFS mergulha em um caminho até não conseguir continuar. Dijkstra não faz isso.
Não é BFS pura
BFS usa fila comum e escolhe por ordem de chegada, boa quando todo peso vale 1.
É busca por menor custo
Dijkstra usa fila de prioridade: sai primeiro quem tem o menor custo acumulado.
Uma forma útil de pensar: Dijkstra parece uma BFS adaptada para grafos com pesos.
Em vez de processar por camada, ele processa pelo menor valor de distância conhecido.
03
O mesmo grafo ponderado da Aula 5
Observe que o caminho visualmente mais “direto” não é necessariamente o mais barato.
04
Relaxamento: o coração do Dijkstra
Suponha que já sabemos que o custo para chegar em B é 4.
distancia[B] = 4
peso(B,E) = 1
novo_custo = 4 + 1 = 5
peso(B,E) = 1
novo_custo = 4 + 1 = 5
distancia[E] = ∞
5 < ∞ ? SIM
distancia[E] = 5
5 < ∞ ? SIM
distancia[E] = 5
Relaxar uma aresta significa perguntar:
“Chegar ao vizinho passando por mim fica mais barato do que o melhor valor conhecido?”
05
Dijkstra animado: A → G
Fila de prioridade
Regra: o item destacado tem o menor custo e será retirado primeiro.
Itens “antigos” podem ficar na fila, mas são ignorados se já existe custo melhor.
Já saiu da fila
Execução
passo 0
Clique em “Próximo” ou “Executar”.
Vértice escolhido
—
A∞
B∞
C∞
D∞
E∞
F∞
G∞
06
Qual caminho venceu?
A
4→
B
1→
E
2→
G
7
custo mínimo de A até G
O caminho A → C → F → G possui o mesmo número de arestas, mas custa 9.
Dijkstra escolhe pelo custo acumulado, não pela quantidade de passos.
07
Dijkstra em Python 3.11
import heapq grafo = { 'A': [('B', 4), ('C', 2)], 'B': [('A', 4), ('D', 5), ('E', 1)], 'C': [('A', 2), ('E', 7), ('F', 3)], 'D': [('B', 5), ('G', 6)], 'E': [('B', 1), ('C', 7), ('G', 2)], 'F': [('C', 3), ('G', 4)], 'G': [('D', 6), ('E', 2), ('F', 4)] } def dijkstra(grafo, origem): # No início, somente a distância da origem é conhecida. dist = { vertice: float('inf') for vertice in grafo } anterior = { vertice: None for vertice in grafo } dist[origem] = 0 # (distância, vértice) fila = [(0, origem)] while fila: # A fila de prioridade retira o menor custo acumulado. distancia_atual, v = heapq.heappop(fila) # Entrada antiga da fila? if distancia_atual > dist[v]: continue for vizinho, peso in grafo[v]: novo_custo = distancia_atual + peso # Relaxamento if novo_custo < dist[vizinho]: dist[vizinho] = novo_custo anterior[vizinho] = v # A nova estimativa volta para a fila e será # processada quando for a menor disponível. heapq.heappush( fila, (novo_custo, vizinho) ) return dist, anterior # Executa o algoritmo completo a partir de A. dist, anterior = dijkstra(grafo, 'A') print(dist['G'])
heapq funciona como uma fila de prioridade:
o menor valor de distância fica disponível primeiro.
08
BFS × Dijkstra
| Característica | BFS | Dijkstra |
|---|---|---|
| Estrutura principal | Fila | Fila de prioridade |
| Pesos das arestas | Iguais | Podem ser diferentes |
| Critério | Menor nº de arestas | Menor custo acumulado |
| Python | deque | heapq |
| Exemplo | Movimentos do cavalo | Rotas com distâncias/custos |
Frase para memorizar:
“BFS escolhe por camada. Dijkstra escolhe pelo menor custo conhecido.”
DFS não entra nessa escolha porque ela não garante menor caminho: ela apenas aprofunda em um caminho.