Modification de l'algorithme de Dijkstra pour les poids de bord tirés de la plage

10

Supposons que j'ai un graphique dirigé avec des poids de bord tirés de la plage [1,,K]K est constant. Si j'essaie de trouver le chemin le plus court en utilisant l'algorithme de Dijkstra , comment puis-je modifier la structure de l'algorithme / des données et améliorer la complexité temporelle en O(|V|+|E|) ?

user1675999
la source
Vous devriez être plus précis, quelle est votre structure de données? Et vous ne pouvez pas obtenir moins d' . Revoir les conférences. O(V+E)
jonaprieto
Ce n'est pas parce que les possibilités de poids de bord distincts sont petites que le nombre de distances est petit.
Joe
3
Commencez par colorier les sommets de votre graphique en bleu, puis subdivisez chaque bord de taille en bords t (en ajoutant t - 1 sommets non colorés), puis exécutez le BFS sur ce nouveau graphique, pour trouver les chemins les plus courts du nœud de départ aux nœuds bleus, c'est O ( | V | + | E | ) si vous avez une constante k . ttt1O(|V|+|E|)k
@SaeedAmiri pourquoi ne pas écrire cela comme une réponse?
Joe
@Joe parce qu'il ne modifie pas dijkstra (au moins directement n'est pas lié à dijkstra).

Réponses:

16

Si les poids de bord sont des entiers dans , vous pouvez implémenter Dijkstra pour qu'il s'exécute en O ( K | V | + | E | ){0,1,,K}O(K|V|+|E|) , en suivant la suggestion de @ rrenaud. Voici une explication plus explicite.

À tout moment, les clés (finies) de la file d'attente prioritaire sont dans une certaine plage , où D est la valeur de la dernière clé retirée de la file d'attente prioritaire. (Chaque clé est au moins D , car la séquence de clés supprimée par l'algorithme de Dijkstra n'est pas décroissante, et chaque clé est au plus D + K , car chaque clé a la valeur d [ u ] + w t ( u , w ) pour un bord ( u ,{D,D+1,,D+K}DDD+Kd[u]+wt(u,w)(u,w) est la distance de la source à un sommet u qui a déjà été supprimé, donc d [ u ] Dd[u]ud[u]D )

Pour cette raison, vous pouvez implémenter la file d'attente prioritaire avec un tableau circulaire de taille K + 1 , chaque cellule contenant un compartiment. Stockez chaque sommet avec la clé k dans le seau dans la cellule A [ h ( k ) ]h ( k ) = k mod ( K + 1 ) . Gardez une trace de DA[0..K]K+1kA[h(k)]h(k)=kmod(K+1)D . Effectuez les opérations comme suit:

  • delete-min : Alors que est vide, incrément D . Ensuite, supprimez et renvoyez un sommet de A [ h ( D ) ]A[h(D)]DA[h(D)] .

  • insérer avec la clé : ajouter le sommet au seau de A [ h ( k ) ]kA[h(k)] .

  • touche décroissante à k : déplacer le sommet de A [ h ( k ) ] à A [ h ( k ) ]kkA[h(k)]A[h(k)] .

L'insertion et la diminution de la clé sont des opérations à temps constant, donc le temps total passé dans ces opérations sera . Le temps total passé en suppression min sera O ( | V | ) ainsi que la valeur finale de D . La valeur finale de D est la distance maximale (finie) de la source à tout sommet (car une suppression-min qui prend i itérations augmente D de i ). La distance maximale est au plus K ( | V | - 1O(|V|+|E|)O(|V|)DDiDiK(|V|1) car chaque chemin a au plus bords. Ainsi, le temps total passé par l'algorithme est O ( K | V | + | E | ) .|V|1O(K|V|+|E|)

Neal Young
la source
J'aime la file d'attente circulaire, c'est bien mieux que mon idée d'avoir essentiellement un tableau de taille K * v où seule une tranche de taille av est utilisée à un moment donné.
rrenaud
Je l'ai implémenté à l'aide d'une double liste chaînée, cela signifie-t-il toujours que c'est O (1) pour trouver la clé min?
user1675999
@ user1675999, je ne suis pas sûr. si votre liste est triée par clé, comment insérez-vous et diminuez-vous efficacement la clé? si votre liste n'est pas triée par clé, comment faire pour supprimer-min efficacement?
Neal Young
5

Je suppose ici que est un entier et que les poids des bords sont intégraux. Sinon, cela ne vous achète vraiment rien, vous pouvez toujours redimensionner les poids de sorte que le bord minimal ait coûté 1 et le maximum a coûté KK1K , de sorte que le problème est identique au problème de chemin le plus court standard.

Algorithme / esquisse de preuve: implémentez la file d'attente prioritaire de cette manière folle comme un tableau de listes indexées par coût et utilisent autrement l'algorithme de Dijkstra standard. Gardez un compteur qui suit le coût de l'article minimum dans le tas. Résolvez l'appel de mise en file d'attente une fois les éléments supprimés par balayage linéaire . Oui, ce genre de sons semble fou, mais constant KK×|V|K vous permet de tricher et de tromper votre intuition algorithmique contre les analyses linéaires. Il vous suffit de numériser à partir du dernier marqueur min car l'algorithme de Disjkstra est agréable pour votre implémentation de file d'attente. Au moment où il demande une mise en file d'attente, les éléments insérés dans la file d'attente sont toujours supérieurs ou égaux au minimum précédent. Le plus long chemin le plus court possible a une longueur, votre coût de numérisation amorti est donc K × | V | = O ( | V | ) si K est constant.K×|V|K×|V|=O(|V|)

rrenaud
la source
-2

vous pouvez utiliser le tri topologique pour trouver la solution, laisser la source avoir le degré 0, aller de chaque bord de la source, si un autre sommet a 0 degré, le mettre dans la file d'attente et continuer à le faire. dans ce cas (sans cycle à l'intérieur du graphique), il peut atteindre V + E car il traverserait chaque sommet et chaque arête une seule fois.

TIANYANG ZHANG
la source
Semble sans rapport avec la question? La question ne suppose pas que le graphique est acyclique, et votre solution n'utilise pas le fait que les poids sont tirés d'une plage constante.
xskxzr