1
vector<int> dijkstra(vector<vector<int>> &vec, int vertices, int edges, int source) 
{
    vector <pair<int,int>> adj[vertices];
    for (int i=0;i<edges;i++)
    {
        int u = vec[i][0];
        int v = vec[i][1];
        int w = vec[i][2];
        
        adj[u].push_back(make_pair(v,w));
        adj[v].push_back(make_pair(u,w));
    }
    
    vector<int> distance(vertices,INT_MAX);
    distance[source]= 0;
    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int> > > pq;
    pq.push(make_pair(0,source));
    
    while(!pq.empty())
    {
        int dis = pq.top().first;
        int node = pq.top().second;
        pq.pop();
        
        for (auto adjacentNode : adj[node])
        {
            int currNode = adjacentNode.first;
            int dfn = adjacentNode.second;
            
            if (dfn+dis < distance[currNode])
            {
                distance[currNode]= dfn+dis;
                pq.push(make_pair(distance[currNode], currNode));
            }
        }
    }

    return distance;
}

I was writing code for Dijkstra's Algorithm using priority queue but forgot to initialize the visited array to keep track of visited vertices. I submitted the code and all the test cases passed. Is the visited array really needed, or am I missing something?

Shroud
  • 35
  • 7

2 Answers2

3

Since your algorithm keeps track of the (so far) shortest distance to a node, the if (dfn+dis < distance[currNode]) statement will prevent the algorithm from revisiting nodes it had already visited, because the loop it made to revisit a node would add to the distance it already had for that revisited node, and so this condition is false (assuming positive weights).

So indeed, you don't need the visited array in this variant of Dijkstra's algorithm. See also how it is not there in the pseudo code that Wikipedia offers.

trincot
  • 317,000
  • 35
  • 244
  • 286
  • This code is giving correct answer for negative weights but dijkstra's algo does not work on negative weights – Shroud Aug 29 '22 at 17:34
  • 1
    Dijkstra's algorithm will not be efficient when weights are negative, and will get into trouble when there are negative cycles. – trincot Aug 29 '22 at 17:36
  • @trincot Dijkstra's is not inefficient when weights are negative, it doesn't work in that case. What the OP has does work, so he doesn't have Dijkstra's. Also, your first statement about the `if` condition not revisiting nodes is false if we can have negative weights, you don't need negative cycles for that to happen. – IVlad Aug 29 '22 at 17:49
  • @IVlad, yes, I had made a sloppy edit that I have reverted again. – trincot Aug 29 '22 at 17:54
1

This isn't really Dijkstra's algorithm, as Dijkstra's involves each node being added and removed from the priority queue at most once. This version will reinsert nodes in the queue when you have negative weight edges. It will also go into an infinite loop if you have negative weight cycles.

Note that the wikipedia version uses a decrease key operation, it does not insert to the priority queue in the if statement.

I don't know which version you're referring to that uses a visited array, but it's likely that visited array achieved the same purpose.

This is closer to the Bellman-Ford algorithm, which can also be implemented with a queue (and it's usually faster in practice if you do it that way than if you do it as shown in most sources by iterating the edges |V| times). A priority queue achieves the same results, but it will be slower than a simple FIFO queue. It was probably fast enough for the online judge you submitted this to.

Bottom line: what you have there isn't Dijkstra's algorithm. The visited array is likely necessary to make it Dijkstra's. You should edit your post to show that version as well so we can say for sure.

IVlad
  • 43,099
  • 13
  • 111
  • 179
  • On the first paragraph: that depends on which variant of Dijkstra one uses. There are versions that put the same node potentially multiple times on the queue. Note also on Wikipedia the phrase *" Yet another alternative is to add nodes unconditionally to the priority queue and to instead check after extraction that no shorter connection was found yet"*. – trincot Aug 29 '22 at 17:56
  • @trincot I don't think it depends. Those versions are wrongly labelled as Dijkstra's algorithm, unless we also agree that the generally accepted statement "Dijkstra's does not work if you have negative weights" is also version-dependant. – IVlad Aug 29 '22 at 17:58
  • OK, so we end up with definition of terms. If you believe Wikipedia is wrong to include those variants on explaining Dijkstra's algorithm, then it's not worth to further discuss this. – trincot Aug 29 '22 at 18:01
  • @trincot yes, I think Wikipedia is wrong here, but why wouldn't it be worth discussing? CLRS makes no mention of such a variant. How do you reconcile that statement on Wikipedia with it also saying "**Unlike Dijkstra's algorithm**, the Bellman–Ford algorithm can be used on graphs with negative edge weights"? – IVlad Aug 29 '22 at 18:05
  • @IVlad Slight change in code, we need visited array which keeps track of nodes whose neighbours are relaxed. So that it won't check visited nodes again and that's the limitation of dijkstra's algo. – Shroud Aug 30 '22 at 08:41
  • @IVlad I have run this code on a test case which contain negative cycle but this algorithm gives the correct shortest path but if we go with the dijkstra algorithm the answer should be wrong. – Shroud Aug 30 '22 at 09:48
  • @Shroud do you mean negative cycle or negative edges? For negative cycles the correct answer is "there's a negative cycle", which your code definitely doesn't do (but can easily be adapted to do it). For negative edges, yes, it looks like your code gives the correct answer, as opposed to Dijkstra's algorithm. Because what you presented is not Dijkstra's algorithm. – IVlad Aug 30 '22 at 09:52
  • @IVlad It was about edges, slightly changed this code added a visited vector which keep track of nodes whose neighbours are processed and the expected ouput is correct now ( according to online judge). Should I edit the code? – Shroud Aug 30 '22 at 09:58
  • https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm @IVlad I am talking about the step 4 on the algorithm. – Shroud Aug 30 '22 at 10:02
  • @Shroud I'm not sure what you mean. Is your current code not correct according to the online judge? – IVlad Aug 30 '22 at 10:03
  • @IVlad yes it is not correct but after adding vistied vector it is giving correct answer – Shroud Aug 30 '22 at 10:05
  • Why did you say it's correct in your initial post then? I haven't debugged the code, but the idea seems correct. – IVlad Aug 30 '22 at 10:10
  • @IVlad It is correct according to online judge but when I tested this on custom test case with negative weights it gave the output,according to code correct ( means it is working fine for negative weight ) but the expected output was wrong (online judge was expecting ) – Shroud Aug 30 '22 at 10:30
  • so visited array is required as this code will fail if test case is tested with negative weights, please correct me if I am wrong – Shroud Aug 30 '22 at 10:33
  • 1
    @Shroud so it sounds like the online judge is specifically testing for a proper Dijkstra's that fails on negative edges. You're correct in that case: you need the visited array (or the `decrease key` implementation on Wikipedia) to pass the online judge test cases. If you want it to work with negative edges too, then this is fine (but you might want to change the queue to a FIFO queue for efficiency). – IVlad Aug 30 '22 at 10:47