【问题标题】:Shortest path in Graph with time limit有时间限制的图中最短路径
【发布时间】:2022-01-20 05:51:21
【问题描述】:

假设我有一个图G,其中有N 顶点和M 边。每条边都有它的长度和时间(比如说以分钟为单位),它需要遍历该边。我需要在图中找到顶点1N 之间的最短路径,这是在T 分钟时间内执行的。 由于时间是更有价值的资源,我们关心的是及时遍历图,并且只有在最短的时间内,我决定使用 Dijkstra 算法,我将每条边的时间视为其权重。我添加了一个向量来存储持续时间。因此,该算法返回最少的时间,而不是最少的长度。一位朋友建议在我的代码中添加此内容:

int answer(int T) {
    int l = 1;
    int r = M; // a very big number
    int answer = M;
    while (l <= r) {
        int mid = (l + r) / 2;
        int time = dijkstra(mid); // the parameter mid serves as an upper bound for dijkstra and I relax the edge only if its length(not time) is less than mid
        if (time <= T) {
            answer = mid;
            r = mid - 1;
        } else {
            l = mid + 1;
        }
    }
    if (best == M) {
        return -1; // what we return in case there is no path in the graph, which takes less than T minutes
    }
    return answer;
}

这是dijkstra 方法(Graphstd::unordered_map&lt;int, std::vector&lt;Node&gt;&gt; adjacencyList member 类的一部分):

int dijkstra(int maxLength) {
        std::priority_queue<Node, std::vector<Node>, NodeComparator> heap;//NodeComparator sorts by time of edge
        std::vector<int> durations(this->numberOfVertices + 1, M);
        std::set<int> visited;
        // duration 1->1 is 0
        durations[1] = 0;
        heap.emplace(1, 0, 0);
        while (!heap.empty()) {
            int vertex = heap.top().endVertex;
            heap.pop();
            // to avoid repetition
            if (visited.find(vertex) != visited.end()) {
                continue;
            }
            for (Node node: adjacencyList[vertex]) {
                // relaxation
                if (node.length <= maxLength && durations[node.endVertex] > durations[vertex] + node.time) {
                    durations[node.endVertex] = durations[vertex] + node.time;
                    heap.emplace(node.endVertex, durations[node.endVertex], 0);
                }
            }
            // mark as visited to avoid going through the same vertex again
            visited.insert(vertex);
        }
        // return path time between 1 and N bounded by maxKilograms
        return durations.back();
    }

这似乎可行,但对我来说似乎效率低下。老实说,我并不完全理解他的想法。在我看来,这就像随机尝试找到最佳答案(因为没有人说边缘的时间与其长度成正比)。我尝试搜索shortest path in graph with time limit,但我找到了找到最快路径的算法,而不是最短有限制的路径。甚至存在这样的算法吗?如何改进我的解决方案?

【问题讨论】:

  • dijkstra 的功能是什么?您希望您的函数答案返回什么? “最佳”变量来自哪里?该算法似乎使用二进制搜索,但很难掌握这么少的信息。请编辑您关于代码的问题。您的问题的一个快速解决方案是修改 dijkstra 算法,以便任何路径花费的时间超过允许的“无限”权重。一次通过就可以了,但请务必检查答案是否有效。
  • 我编辑了我的问题。我希望现在信息足够了。感谢您调查我的问题。

标签: c++ algorithm graph-theory shortest-path


【解决方案1】:

这是什么?

int time = dijkstra(mid);

这当然不是 Dijkstra 算法的实现!

Dijkstra 算法需要起始节点并返回从起始节点到其他节点的最短路径。

您将需要一个函数来返回起始节点和结束节点之间所有花费小于 T 的不同路径。然后您可以搜索它们以找到最便宜的路径。

Search graph for all distinct paths from start to end
Discard paths that take more then T
Select cheapest path.

【讨论】:

  • 它是 dijkstra 但直接返回 1 和每个其他顶点之间的距离。这就是为什么它不需要任何来源。它被硬编码为 1。
  • 怎么样?它似乎返回一个整数!
  • 是的。我没有正确地表达自己。由于我只需要顶点 1 和 N 之间的距离,因此我直接返回向量的最后一个元素(即 1 和 N 之间的距离)。我编辑了我的答案,所以现在你应该可以看到 dijkstra() 方法
【解决方案2】:

寻找资源受限的最短路径是 NPHard。大多数解决此问题的方法都采用标记方案,这是动态规划的一种特殊形式。您可以使用可用的库来完成此操作。请参阅 here 了解提升实现。

【讨论】:

    猜你喜欢
    • 2021-11-27
    • 1970-01-01
    • 2016-02-04
    • 2014-07-15
    • 1970-01-01
    • 2014-02-19
    • 2019-08-21
    相关资源
    最近更新 更多