Suponha que eu tenha um gráfico direcionado com pesos de arestas desenhados no intervalo onde é constante. Se estou tentando encontrar o caminho mais curto usando o algoritmo de Dijkstra , como posso modificar a estrutura do algoritmo / dados e melhorar a complexidade do tempo para ?
algorithms
data-structures
shortest-path
weighted-graphs
user1675999
fonte
fonte
Respostas:
Se os pesos das arestas forem números inteiros em , você poderá implementar o Dijkstra para executar no tempo O ( K | V | + | E | ) , seguindo a sugestão de @ rrenaud. Aqui está uma explicação mais explícita.{0,1,…,K} O(K|V|+|E|)
A qualquer momento, as teclas (finitas) na fila de prioridade estão em algum intervalo , em que D é o valor da última chave removida da fila de prioridade. (Cada chave é pelo menos D , porque a sequência de chaves removidas pelo algoritmo de Dijkstra não diminui e cada chave é no máximo D + K , porque cada chave tem o valor d [ u ] + w t ( u , w ) para alguma vantagem ( u ,{D,D+1,…,D+K} D D D+K d[u]+wt(u,w) onde d [ u ] é a distância da fonte a algum vértice u que já foi removido, então d [ u ] ≤ D. )(u,w) d[u] u d[u]≤D
Por isso, é possível implementar a fila de prioridade com uma matriz circular do tamanho K + 1 , com cada célula contendo um balde. Armazene cada vértice com a chave k no balde na célula A [ h ( k ) ] onde h ( k ) = k mod ( K + 1 ) . Mantenha o controle de D . Execute as operações da seguinte maneira:A[0..K] K+1 k A[h(k)] h(k)=kmod(K+1) D
eliminar-min : Enquanto está vazio, incremento D . Em seguida, exclua e retorne um vértice de A [ h ( D ) ] .A[h(D)] D A[h(D)]
inserir com a chave : adicione o vértice ao balde de A [ h ( k ) ] .k A [ h ( k ) ]
tecla de diminuição para k ′ : mova o vértice de A [ h ( k ) ] para A [ h ( k ′ ) ] .k k′ A [ h ( k ) ] A[h(k′)]
Inserir e diminuir chave são operações de tempo constante; portanto, o tempo total gasto nessas operações será . O tempo total gasto em apagar-min será O ( | V | ) mais o valor final de D . O valor final de D é a distância máxima (finito) a partir da fonte para qualquer vértice (porque uma exclusão min que leva i iterações aumenta D por i ). A distância máxima é no máximo K ( | V | - 1O(|V|+|E|) O(|V|) D D i D i porque cada caminho tem no máximo | V | - 1 arestas. Assim, o tempo total gasto pelo algoritmo é O ( K | V | + | E | ) .K(|V|−1) |V|−1 O(K|V|+|E|)
fonte
Suponho aqui que é um número inteiro e os pesos das arestas são integrais. Caso contrário, ele realmente não comprar qualquer coisa, você pode pesos sempre redimensionar para que a borda min custou 1 eo máximo tem custo K , então o problema é idêntico ao problema do caminho mais curto padrão.K 1 K
Esboço de algoritmo / prova: implemente a fila de prioridade desse tipo maluco como uma matriz de listas codificadas pelo custo e, de outra forma, usam o algoritmo padrão do Dijkstra. Mantenha um contador que rastreie o custo do item mínimo na pilha. Resolva a chamada de remoção da fila depois que os itens forem excluídos pela varredura linear . Sim, isso parece insano, mas constante KK×|V| K vamos enganar e enganar sua intuição algorítmica contra verificações lineares. Você só precisa procurar a partir do último marcador min, porque o algoritmo do Disjkstra é bom para a implementação da fila. No momento em que solicita uma desenfileiramento, os itens inseridos na fila são sempre maiores ou iguais ao mínimo anterior. O caminho mais curto mais longo possível possui comprimento , então seu custo de digitalização amortizado é K × | V | = O ( | V | ) se K for constante.K×|V| K×|V|=O(|V|)
fonte
você pode usar a classificação topológica para encontrar a solução, deixar a fonte ter o grau 0 e ir de cada extremidade da fonte; se outro vértice tiver 0 grau, coloque-o na fila e continue fazendo isso. nesse caso (sem ciclo dentro do gráfico), ele pode atingir V + E, pois passaria por todos os vértices e arestas uma vez e apenas uma vez.
fonte