【问题标题】:Dijkstra shortest path with minimum steps最小步数的 Dijkstra 最短路径
【发布时间】:2015-05-23 20:02:04
【问题描述】:

我需要实现一个程序,给定一个在弧上具有正成本的有向图,打印从 x 到 y 的最小成本以及从 x 到 y 的所有路径的最小步数,以这样的最小成本. 我编写了一个程序来执行此操作,但有时它采用的路径没有最少的步骤数。 这是我的代码:

#include <iostream>
#include <vector>
#include <queue>
#include <climits>

using namespace std;

typedef pair<int, int> Warc;
typedef vector<vector<Warc>> Wgraph;

int dijkstra(const Wgraph& g, int x, int y, vector<int>& p) {
  int n = g.size();
  vector<int> d(n, INT_MAX); //costs
  p = vector<int>(n, -1); //parent of each vertice
  d[x] =0;
  vector<bool> S(n, false);
  priority_queue<Warc, vector<Warc>, greater<Warc>> Q;
  Q.push(Warc(0, x));
  while(not Q.empty()) {
    int u = Q.top().second;
    Q.pop();
    if(u == y) return d[u];
    if(not S[u]) {
      S[u] = true;
      for(Warc a : g[u]) {
        int v = a.second;
        int c = a.first;
        if(d[v] > d[u] + c) {
         d[v] = d[u] + c;
         p[v] = u;
         Q.push(Warc(d[v], v));
       }
      }
    }
  }
  return -1;
}

int main() {
  int n; //# of vertices
  while(cin >> n) {
    int m; //# of arcs
    cin >> m;
    Wgraph g(n);
    for(int i = 0; i<m; ++i) {
      int u, v;
      int c;
      cin >> u >> v >> c; // arc: u->v with cost C
      g[u].push_back(make_pair(c, v));
    }
    int x, y;
    cin >> x >> y; //origin and end
    vector<int> p; //p[i]= parent of vertice i
    int path = dijkstra(g, x, y, p);
    if(path == -1) cout << "no path from " << x << " to " << y << endl;
    else {
        int s = 0;
        int i = y;
        while(i != x) {
            ++s;
            i = p[i];
        }
        cout << "cost " << path-s << ", " << s << " step(s)" << endl;
    }
  }
}

谢谢。

【问题讨论】:

  • 您是否尝试过使用调试器来单步调试代码?您是否尝试将其分解为更小的单元并为它们编写单元测试?
  • 请注意,您的实现的复杂度将是O(m log m),而它应该是O(n log n)(其中n 是节点数,m 是边数):优先级队列在需要存储节点的同时存储边。它还需要在优先级队列中移动节点,std::priority_queue&lt;T&gt; 不支持的操作。
  • 您的算法只使用它找到的第一条最短路径。如果最小步长部分的最后一步很小,而多步路径中的最后一步较大,则优先使用多步路径。

标签: c++ c++11 graph dijkstra


【解决方案1】:

问题是您只考虑优先级队列中的距离。因此,将使用随机的最后一条边来完成路径,但只会考虑其中一条。您可以创建一个更高级的距离,除了距离之外还要考虑路径的长度:主要权重是距离,但对于相同的距离,您会认为来自较短路径的边缘更短。

请注意,您的算法具有错误的复杂性:它具有复杂性 O(m log m) 而不是 O(n log n)n 是节点数,m 是边数),因为您将边存储在优先级队列中而不是节点。 Dijstra 的算法仅在存储节点并根据需要调整其在优先级队列中的位置时才有效——std::priority_queue&lt;T&gt; 不支持该操作。

【讨论】:

    猜你喜欢
    • 2014-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多