Algorithme de Dijkstra avec des poids négatifs

peut-on utiliser L'algorithme de Dijkstra avec des poids négatifs?

STOP! Avant de penser "lol nub, vous pouvez simplement l'infini hop entre deux points et d'obtenir une infinité pas cher chemin", je suis de plus en plus la pensée de chemins.

une application pour ceci serait un terrain montagneux avec des points sur elle. Évidemment passer de haut en bas ne prend pas d'énergie, en fait, il génère de l'énergie (donc un poids de chemin négatif)! Mais revenir en arrière ne marcherait pas. sauf si tu es Chuck Norris.

je pensais augmenter le poids de tous les points jusqu'à ce qu'ils soient non-négatifs, mais je ne suis pas sûr que cela fonctionne.

32
demandé sur Kromster 2011-05-11 01:13:14

7 réponses

aussi longtemps que le graphe ne contient pas de cycle négatif (un cycle dirigé dont les poids de bord ont une somme négative), il aura un chemin le plus court entre deux points, mais L'algorithme de Dijkstra n'est pas conçu pour les trouver. L'algorithme le plus connu pour trouver les chemins Les plus courts d'une source unique dans un graphique dirigé avec des poids de bord négatifs est le algorithme Bellman-Ford. Cela a un coût, cependant: Bellman-Ford exige O (|V|·| E/) temps, tandis que Dijkstra il faut du temps O (|E | + |V|log| V|), qui est asymptotiquement plus rapide pour les graphiques épars (où E est O (|V|)) et les graphiques denses (où E est O (|V / ^2)).

dans votre exemple de terrain montagneux (nécessairement un graphique dirigéperpétuel machine à mouvement.

augmenter tous les poids d'une valeur constante pour qu'ils soient non négatifs ne fonctionnera pas. Pour voir ceci, considérez le graphique où il y a deux chemins de A à B, Un traversant un seul bord de longueur 2, et un traversant les bords de longueur 1, 1, et -2. Le deuxième chemin est plus court, mais si vous augmentez tous les poids de bord de 2, le premier chemin a maintenant la longueur 4, et le deuxième chemin a la longueur 6, inversant les chemins Les plus courts. Cette tactique ne fonctionnera que si tous chemins possibles entre deux points d'utiliser le même nombre d'arêtes.

55
répondu D Coetzee 2016-05-30 21:28:07

si vous lisez la preuve d'optimalité, une des hypothèses est que tous les poids sont non négatifs. Donc, aucun. Comme Bart le recommande, utilisez Bellman-Ford s'il n'y a pas de cycles négatifs dans votre graphique.

Vous devez comprendre qu'un négatif de bord n'est pas seulement un nombre négatif - - - - - cela implique un réduction dans le coût du chemin. Si vous ajoutez un négatif bord de votre chemin, vous avez moins le coût du chemin - - - si vous incrémentez les poids de sorte que ce bord est maintenant non-négatif, il n'a plus Cette propriété de réduction plus et donc c'est un graphique différent.

je vous encourage à lire la preuve d'optimalité --- là, vous verrez que l'hypothèse que l'ajout d'un bord à un chemin existant ne peut qu'augmenter (ou ne pas affecter) le coût du chemin est critique.

3
répondu Jacob 2011-05-10 21:48:56

Vous pouvez utiliser Dijkstra sur un négatif pondérée graphique, mais vous devez d'abord trouver le bon décalage pour chaque Sommet. C'est essentiellement ce que fait L'algorithme de Johnson. Mais ce serait exagéré puisque Johnson utilise Bellman-Ford pour trouver le poids offset (s). Johnson est conçu pour tous les chemins Les plus courts entre les paires de Sommets.

http://en.wikipedia.org/wiki/Johnson%27s_algorithm

1
répondu Justin 2012-01-17 04:10:31

il existe en fait un algorithme qui utilise L'algorithme de Dijkstra dans un environnement de chemin négatif; il le fait en supprimant tous les bords négatifs et en rééquilibrant le graphique en premier. Cet algorithme est appelé "algorithme de Johnson".

la façon dont il fonctionne est en ajoutant un nouveau noeud (disons Q) qui a 0 coût de traverser à chaque autre noeud dans le graphe. Il exécute ensuite Bellman-Ford sur le graphique à partir du point Q, obtenir un coût pour chaque noeud en ce qui concerne Q Que nous appellerons q[x], qui soit 0 ou un nombre négatif (comme les chemins d'accès).

-3 - > b, donc si on ajoute un noeud Q qui a 0 coût pour tous ces noeuds, alors q[A] = 0, q[b] = -3.

nous rééquilibrons alors les bords en utilisant la formule: poids + q [source] - q[destination], de sorte que le nouveau poids de a - >b est -3 + 0 - (-3) = 0. Nous faisons cela pour tous les autres bords dans le graphique, puis supprimer Q et ses bords sortants et voila! Nous avons maintenant un graphique de rééquilibrage avec aucun des bords négatifs sur lesquels on peut lancer dijkstra!

Le temps d'exécution est O(nm) [bellman-ford] + n x O(m log n) [n Dijkstra] + O(n^2) [poids calcul] = O (n log n) temps

Plus d'info: http://joonki-jeong.blogspot.co.uk/2013/01/johnsons-algorithm.html

1
répondu Evil Washing Machine 2013-05-16 23:41:33

en fait je pense que ça va marcher pour modifier les poids de bord. Pas avec un décalage, mais avec un facteur. Supposons qu'au lieu de mesurer la distance, vous mesuriez le temps requis entre le point A et le point B.

poids = temps = distance / vitesse

vous pouvez même adapter la vitesse en fonction de la pente pour utiliser la physique si votre tâche est pour de vraies montagnes et voiture/vélo.

0
répondu Karussell 2012-10-10 11:31:54

Oui, vous pouvez le faire avec l'ajout d'une étape à la fin c'est à dire

            If v ∈ Q, Then Decrease-Key(Q, v, v.d)
            Else Insert(Q, v) and S = S \ {v}.
0
répondu sa_nyc 2012-12-09 02:00:03

un arbre d'expression est un arbre binaire dans lequel toutes les feuilles sont des opérandes (constantes ou variables), et les noeuds non foliaires sont des opérateurs binaires (+,-,/, *,^). Implémenter cet arbre pour modéliser les polynômes avec les méthodes de base de l'arbre y compris les suivantes:

  1. Une fonction qui calcule la dérivée d'un polynôme.
  2. Évaluer un polynôme pour une valeur donnée de x.

[20] Utiliser les règles suivantes pour les dérivés: Dérivés(constante) = 0 Dérivés(x) = 1(Dérivée de P(x) + Q(y)) = (Dérivée de P(x)) + Dérivés(Q(y)) Dérivé(P(x) - Q(y)) = (Dérivée de P(x)) - Dérivé(Q(y)) Dérivé(P(x) * Q(y)) = P(x)*Dérivés(Q(y)) + Q(x)*Dérivés(P(x)) Dérivé(P(x) / Q(y)) = P(x)*Dérivés(Q(y)) - Q(x)*Dérivés(P(x)) Dérivé(P(x) ^ Q(y)) = Q(y) * (P(x) ^(Q(y) - 1)) * Dérivés(Q(y))

-2
répondu zile 2012-12-14 06:43:10