简体   繁体   中英

Dijkstra's algorithm implementation for undirected cyclic graphs without priority queues

How can i implement the Dijkstra using only queues instead of priority queues .Is this possible ? if not,why ? This is My Code in java.. whats my mistake ?
"S" is the starting node "W" is the weight "N" is the size of the matrix. I added 1 to the length of the adj matrix since the first node is "1".

This is a problem from HackerRank Link : https://www.hackerrank.com/challenges/dijkstrashortreach

  import java.io.*;
  import java.util.*;

public class Solution {

public static void main(String[] args) {

    Scanner in = new Scanner (System.in);
    int cases = in.nextInt();

    for(int i=0; i<cases; i++){
        int N = in.nextInt();
        int M = in.nextInt();
        int adj[][] = new int[N+1][N+1];

        for(int j=0; j<N+1; j++){
            for(int k=0; k<N+1; k++){
                adj[j][k] = 0;
            }
        }

        for(int j=0; j<M; j++){
            int A = in.nextInt();
            int B = in.nextInt();
            int W = in.nextInt();

            adj[A][B] = W;
            adj[B][A] = W;
        }

        int S  = in.nextInt();

        Queue<Integer> que = new  LinkedList<Integer>();
        que.add(S);

        int dist[] = new int[N+1];
        Arrays.fill(dist,Integer.MAX_VALUE);
        boolean vis[] = new boolean[N+1];

        dist[S] = 0;
        vis[S] = true;

        while(!que.isEmpty()){
            int q = que.poll();

            for(int j=1; j<=N; j++){
                if(!vis[j]&&q!=j && adj[q][j]!=0){

                    if(dist[j]>dist[q]+adj[q][j]){
                      dist[j] = dist[q]+adj[q][j];
                        que.add(j);
                    } 
                }
            }
            vis[q] = true;
        }

        for(int j=1; j<=N; j++){
            if(dist[j]!=0)
            System.out.print(dist[j]+" ");
        }
    }

}

}

Yes, it is possible to implement it like that but it's less than optimal. Because you use queues instead of priority queues you may have to expand the same portion of the graph multiple times. Because of that you replace the logN with something like N^2 (if i'm not mistaking).

If you don't expand a node multiple times (like you do in your code) then it's wrong because you use a cost that is higher than the minimum. Imagine that you have 2 nodes with a direct link of cost 20 or an indirect link through a third node with cost 1 on both edges. You would expact the second node assuming minimum distance is 20 (because it arrived first in the queue) but if you waited you would find a path with cost 2. Add more nodes to the indirect path if this is not already obvious.

At least do a linear search to find the minimum to bring it back to N (overall complexity O(N^2) with your setup). The best implementation has complexity O((N+M)logN).

Another mistake in your code is in reading the data:

 for(int j=0; j<M; j++){
        int A = in.nextInt();
        int B = in.nextInt();
        int W = in.nextInt();

        adj[A][B] = W;
        adj[B][A] = W;
    }

According to the problem statement you can have multiple edges between two nodes. You only use the last one. Switch to take the minimum and you should be good.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM