Dijkstra的算法实现用于没有优先级队列的无向循环图

时间:2015-09-25 11:06:44

标签: algorithm queue shortest-path

如何仅使用队列而不是优先级队列来实现Dijkstra 。这可能吗 ?如果没有,为什么?这是我在java中的代码..我的错是什么?
" S"是起始节点" W"是重量" N"是矩阵的大小。我将adj矩阵的长度加1,因为第一个节点是" 1"。

这是来自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]+" ");
        }
    }

}

}

1 个答案:

答案 0 :(得分:0)

是的,可以像这样实现它,但它不是最佳的。 因为您使用队列而不是优先级队列,所以您可能需要多次展开图表的相同部分。因此你用N ^ 2替换了logN(如果我没有误会)。

如果您不多次展开节点(就像在代码中那样),那么这是错误的,因为您使用的成本高于最小值。想象一下,您有2个节点,其成本为20的直接链接,或者是通过第三个节点的间接链接,两个边缘的成本为1。假设最小距离为20(因为它首先到达队列中),您将表达第二个节点,但是如果您等待,则会找到成本为2的路径。如果尚未显示,则向间接路径添加更多节点。

至少进行线性搜索以找到将其恢复到N的最小值(使用您的设置时的总体复杂度O(N ^ 2))。最佳实现具有复杂度O((N + M)logN)。

代码中的另一个错误是读取数据:

 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;
    }

根据问题陈述,您可以在两个节点之间有多个边。你只使用最后一个。切换到最低限度你应该是好的。