【发布时间】: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