【问题标题】:Shortest path question involving transfer in cyclic graph循环图中涉及转移的最短路径问题
【发布时间】:2022-01-16 16:03:29
【问题描述】:

我正在尝试解决图形问题:
有(n+1)条城市(编号从0到n),以及(m+1)条公交线路(编号从0到m)。
(一条线可能包含重复的城市,这意味着该线有一个循环。)
每条线路覆盖多个城市,从城市 i 到城市 j 需要 t_ij(不同线路的 t_ij 可能不同)。
此外,每次上车都需要额外的transfer_time

一条边看起来像这样:城市 i --(time)-->city2
Example1:
n = 2,m = 2,开始 = 0,结束 = 2
第 0 行:
0 --(1)--> 1 --(1)--> 2; transfer_time = 1
第 1 行:
0 --(2)--> 2; transfer_time = 2
Line0 取 1+1+1 = 3,line1 取 4,所以最小值为 3。

示例 2
n = 4,m = 0,开始 = 0,结束 = 4
第 0 行:
0 --(2)--> 1 --(3)--> 2 --(3)-->3 --(3)--> 1 --(2)--> 4; transfer_time = 1
需要1(0点进)+2(0到1)+1(下车进、转)+2=6

我尝试使用 Dijkstra 算法解决它,但无法处理带循环的图形(如 Example2)。 下面是我的代码。

struct Edge {
    int len;
    size_t line_no;
};

class Solution {

public:
    Solution() = default;

    //edges[i][j] is a vector, containing ways from city i to j in different lines
    int findNearestWay(vector<vector<vector<Edge>>>& edges, vector<int>& transfer_time, size_t start, size_t end) {
        size_t n = edges.size();
        vector<pair<int, size_t>> distance(n, { INT_MAX / 2, -1 }); //first: len, second: line_no
        distance[start].first = 0;
        vector<bool> visited(n);
        int cur_line = -1;
        for (int i = 0; i < n; ++i) {
            int next_idx = -1;
            //find the nearest city
            for (int j = 0; j < n; ++j) {
                if (!visited[j] && (next_idx == -1 || distance[j].first < distance[next_idx].first))
                    next_idx = j;
            }
            visited[next_idx] = true;
            cur_line = distance[next_idx].second;
            //update distance of other cities
            for (int j = 0; j < n; ++j) {
                for (const Edge& e : edges[next_idx][j]) {
                    int new_len = distance[next_idx].first + e.len;
                    //transfer
                    if (cur_line == -1 || cur_line != e.line_no) {
                        new_len += transfer_time[e.line_no];
                    }
                    if (new_len < distance[j].first) {
                        distance[j].first = new_len;
                        distance[j].second = e.line_no;
                    }
                }
            }
        }

        return distance[end].first == INT_MAX / 2 ? -1 : distance[end].first;
    }
};

有没有更好的做法来解决它?提前致谢。

【问题讨论】:

  • 名字是循环,不是圆。再看看你访问过的标志,我还没有完全分析你的代码,但我有疑问。一步一步调试你的代码,看看每一步是否产生你期望的结果。
  • 感谢您的评论,我已更正。总的来说,我使用 Dijkstra。距离数组中的元素有一个额外的标签(对的第二个)来显示我到达城市的方式。

标签: c++ graph shortest-path


【解决方案1】:

您的visited 设置看起来不对。您将输入 Djikstra 算法的“节点”不能简单地是城市,因为这不能让您模拟城市内从一条线路切换到另一条线路的成本。每个节点必须是一个pair,由一个城市号和一个公交线路号组成,代表你当前乘坐的公交线路。总线编号可以为-1,表示您不在总线上,起始节点和目标节点的总线编号为-1。

那么每条边代表要么留在您当前乘坐的线路上以前往下一个城市,要么在您当前的城市下车(免费),或者在您所在城市的公交线路上当前城市(有转移费用)。

你说城市的编号是从 0 到 n,但我看到一堆循环在 n - 1 处停止(因为它们使用 &lt; n 作为循环条件),所以这可能是另一个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多