6

Will Dijkstra's algorithm work on a graph with negative edges if it is acyclic (DAG)? I think it would because since there are no cycles there cannot be a negative loop. Is there any other reason why this algorithm would fail?

Thanks [midterm tomorrow]

Marcus
  • 9,032
  • 11
  • 45
  • 84
  • 1
    You're looking for Bellman-Ford-Moore. How (and, indeed, whether) Dijkstra's algorithm fails in such a case depends on how exactly Dijkstra's algorithm was written down in your textbook. – tmyklebu Mar 11 '15 at 21:01

3 Answers3

12

Consider the graph (directed 1 -> 2, 2-> 4, 4 -> 3, 1 -> 3, 3 -> 5):

  1---(2)---3--(2)--5
  |         |
 (3)      (2)
  |         |  
  2--(-10)--4

The minimum path is 1 - 2 - 4 - 3 - 5, with cost -3. However, Dijkstra will set d[3] = 2, d[2] = 3 in the first step, then extract node 3 from its priority queue and set d[5] = 4. Since node 3 was extracted from the priority queue, and Dijkstra does not push a given node to its priority queue more than once, it will never end up in it again, so the algorithm won't work.

Dijkstra's algorithm does not work with negative edges, period. The absence of a cycle changes nothing. Bellman-Ford is the one that can detect negative cost cycles and works with negative edges. Dijkstra will not work if you can have negative edges.

If you change Dijkstra's algorithm such that it can push a node to the priority queue more than once, then the algorithm will work with negative cost edges. But it is debatable if the new algorithm is still Dijkstra's: I would say you get Bellman-Ford that way, which is often implemented exactly like that (well, usually a FIFO queue is used and not a priority queue).

IVlad
  • 43,099
  • 13
  • 111
  • 179
  • Question. Suppose in a changed Dijkstra like you mention, node 3 is added to the priority cue once more. That wouldn't have the effect that node 2 will be visited. Could you explain more on this "pushing more than once"? – Gerard Jul 30 '16 at 21:44
  • @Gerard node `2` will be visited anyway. First, you extract node `1` from the queue, since that is the start node. Then you update the distances from it: `d[3] = 2, d[2] = 3`. You add nodes `3` and `2` to the priority queue. Then you extract `3`, since that is the node with minimum distance to it in the queue. You update `d[4] = 4, d[5] = 4`, and add nodes `4, 5` to the queue. Then you extract node `2`, update d[4] = -7`, add `4` to the queue. Then you extract node `4`, update `d[3] = -5`, and **add node `3` to the queue again**, which will lead to finding the optimal path of cost `-3`. – IVlad Jul 31 '16 at 08:41
  • @Gerard in the classical Dijkstra's algorithm, it wouldn't be allowed to add node `3` to the priority queue again. After we extracted it when it had `d[3] = 2`, we wouldn't add it again, potentially leading to wrong answers when having negative cost edges. – IVlad Jul 31 '16 at 08:44
  • If I understand correctly you 1) remove the stop criterium of classical Dijkstra `if (endnode.IsVisited) break;`? Then 2) you say when an alternative node *would have been* visited in classical Dijkstra, only in that case you quickly re-add to the priority queue? – Gerard Jul 31 '16 at 09:23
  • That will work I believe. The problem may very well be, that in a large graph, it could take very long before the alternative route with a negative lenth will be revisited. Suppose a succesfull route gets -1000 in an early stage and its total distance in the endpoint is +100. Because of the early -1000 it could be that 90% of the netwerk is on top of the priority queue and you have to wait untill at last another route also gets -1000 and wins the algortihm wiht a total distance of +90. – Gerard Jul 31 '16 at 09:29
  • @Gerard 1) you could say I remove that condition, yes. In my idea of classical Dijkstra, each node is added to the priority queue at the beginning of the algorithm, then the algorithm continues while the queue is not empty, extracting a node from it and updating its neighbors. In this variant, the condition is the same, except that you also add the updated neighbors back to the priority queue if they aren't already in it. 2) Yes, in the worst case, each node can enter the queue `|V| - 1` times, as is the case for the Bellman-Ford algorithm. So the new algorithm is basically Bellman-Ford... – IVlad Jul 31 '16 at 11:13
  • Ok. It would be interesting to compare classical Bellman-Ford with Dijkstra+Restore-Updated. – Gerard Jul 31 '16 at 11:24
0

I think Dijkstra's algorithm will work for DAG if there is no negative weight. Because Dijkstra's algorithm can't give the right answer for negative weighted edges graph. But sometimes it does based on graph type.

0

Pure implementation of Dijkstra's will fail , whenever there is a negative edge weight. The following variant will still work for given problem scenario.

  1. Every time an edge u -> v is relaxed, push a pair of (newer/shorter distance to v from source) into queue. This causes more than one copy of the same vertex in queue with different distances from source.
  2. Continue to update the distance until queue is empty.

The above variant works, even if negative edges are present. But not in case if there is negative weight cycle. DAG is acyclic so, we don't have to worry about negative cycles.

There is more efficient way to calculate shortest path distances O(V+E) time for DAGs using topological ordering. More details can be found here

imswapy
  • 112
  • 2
  • 7