Can anyone pass me to know why this implementation of the Dijkstra algorithm does not work for negative weights?

advertisements

This question already has an answer here:

  • Negative weights using Dijkstra's Algorithm 6 answers

I've looked at the implementation of dijkstra's algorithm found here , but it seems to work fine for negative weights.

Specifically, the relax method updates the vertex's distance in the priority queue or inserts it back in if it wasn't originally in the queue.

And since there aren't any checks to make sure we don't reinsert an already known vertex, wouldn't this implementation be more like a bellman-ford algorithm where we keep inserting vertices to visit and relax until run out of edges that reduce distance?

For example:

When running it on the image below with A as the source, we first determine the following distances:

C = 0
B = 1
D = 99

Then after our queue removals, we are left with (D, 99), which makes us visit vertex D and relax it. When relaxing vertex D, we find that (D to B = -300), which makes the distance to B to be -201. Now using the "relax" method above, we reinsert (B, -201) back in the queue. Now we take the min of the queue which is the (B, -201) that we just inserted. From this, we relax B and we can get the distance to C to be -200.

I know that any negative cycle will make the program not terminate, but what if we are given a graph with no negative cycle? Hopefully I'm not missing anything trivial here. Thanks for any help!


Dijkstra is based on fact, that once the node is visited and all of its edges "used", it is NEVER visited anymore and therefore the complexity is low (no need for "re-balancing the whole graph".)

Both of this is based on non-negative edges, because if there is negative one, you have to "re-balance" them and complexity can rise a lot. And as you mentioned, cycles with negative cycles do not end at all.


The reason the author throws exception is because he does not want handle "not valid" graph and especially endless cycles.


PS : Your particular graph actually SHOULD be solvable by Dijkstra, but imagine this graph with negative edge and no cycles:

A ->(1) B ->(1) -> C
|      (-300)
v       ^
(5)     |
D ->(1) E

You actually solve

B=1
C=2

And after this you CLOSE the A, B and C and do not want to enter them again. But after this you find that A->D->E->B is -294 and then you have re-enter all other values.

To imagine why this is so bad, I give you another example

    A ->(1) B ->(1) -> C -> SUPERGRAPH
    |    (-999999)
    v       ^
  (99999)   |
    D ->(1) E

So now A->D is extremely high value and C is pointing to some SUPERGRAPH which however do not go over 99999 in total "length" from A.

What happens? Even if this works and there is no other cycles, you solve the whole supergraph from A, but after that, you find that actually A->B is much shorter and you have to solve the whole SUPERGRAPH again. If you have more of situations like this, for each one, you have to run Dijkstra alghoritm once again.