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

4 2 5 1 7 3 6 2 4 A B C D E F G
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
distancia[E] =

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

4 2 5 1 7 3 6 2 4 A B C D E F 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ísticaBFSDijkstra
Estrutura principalFilaFila de prioridade
Pesos das arestasIguaisPodem ser diferentes
CritérioMenor nº de arestasMenor custo acumulado
Pythondequeheapq
ExemploMovimentos do cavaloRotas 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.