如何仅使用队列而不是优先级队列来实现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]+" ");
}
}
}
}
答案 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;
}
根据问题陈述,您可以在两个节点之间有多个边。你只使用最后一个。切换到最低限度你应该是好的。