【问题标题】:Counter example (graph with negative weight) for Dijkstra algorithm with binary heap [duplicate]具有二进制堆的 Dijkstra 算法的反例(负权图)[重复]
【发布时间】:2015-05-28 15:59:32
【问题描述】:

我想知道是否有人可以给出一个不适用于以下代码的反例(具有负权重的有向图)(具有二进制堆的 Dijkstra 算法)。我尝试了几个示例,但似乎可以正常使用负边缘,只要我们有更好的方法到达某个节点,它就会更新其所有相邻节点的距离。以下是示例

(0) ----2----> (3) -----1-----> (4)
 |              ^
 4              |
 |             -9
 v              |  
(1) ----6----> (2)               

it will print out => 0, 4, 10, 1, 2 

还有

(0) ---1---> (1) ---1---> (2)
 |                         ^
 |                         |
100                      -5000
 |                         |
 \---------> (3) ----------/

this will print => 0, 1, -4900, 100 

以下是Java中的代码

public static void dijkstra(DirectedGraph G, int source) {
    int[] distTo = new int[G.V()];
    Arrays.fill(distTo, Integer.MAX_VALUE);
    distTo[source] = 0;
    PriorityQueue<Node> pq = new PriorityQueue<Node>();
    pq.add(new Node(source, 0));

    while (!pq.isEmpty()) {
        Vertex vertex = pq.poll();
        for (WeightedEdge edge : G.adjTo(vertex.node)) {
            if (edge.weight + distTo[edge.from] < distTo[edge.to]) {
                 distTo[edge.to] = distTo[edge.from] + edge.weight;
                 Vertex adjNode = new Vertex(edge.to, distTo[edge.to]);
                 if (pq.contains(adjNode))
                      pq.remove(adjNode);
                 pq.add(adjNode);
            }
        }
    }
    for (int dist : distTo)
        System.out.print(dist + " ");
}

static class Vertex implements Comparable<Vertex> {
      int node;
      int weight;

      public Vertex(int node, int weight){
             this.node = node;
             this.weight = weight;
      }

      @Override
      public int compareTo(Vertex other) {
             return weight - other.weight;
      }

}

public class DirectedGraph {
       private final int V;
       private int[][]   G;

       public int V() {
              return V;
       }

       public DirectedGraph(int V) {
              this.V = V;
              G = new int[V][V];
       }

       public void addEdge(int v, int w, int weight) {
              G[v][w] = weight;
       }

       public List<WeightedEdge> adjTo(int v) {
              List<WeightedEdge> edges = new LinkedList<WeightedEdge>();
              for (int i = 0; i < V; i++)
                  if (G[v][i] != 0)
                     edges.add(new Edge(v, i, G[v][i]));
              return edges;
       }

}

【问题讨论】:

  • @gtgaxiola 我实际上尝试了答案中的一个例子,它对我的​​代码有负面影响

标签: java algorithm graph dijkstra shortest-path


【解决方案1】:

在 Dijkstra 中,您应该维护已访问节点的列表。一旦你展开一个节点,你就知道你已经计算出了从根节点到达该节点的最佳方式,并且你不会再次将此节点推送到队列中。

这就是 Dijkstra 的本质。如果您不维护该列表,您的代码将陷入负循环的无限循环。您可以使用 Bellman-ford 算法计算单源最短路径并检测是否存在负循环。

【讨论】:

  • 这是有道理的......但仍然想知道我的这段代码是否适用于负权重但不是负循环?
猜你喜欢
  • 2018-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-11
  • 1970-01-01
  • 2011-04-19
  • 2016-05-07
  • 2015-04-19
相关资源
最近更新 更多