次短路径是盲区啊!比赛时硬是不知道,用DFS暴力超时,又看不懂BFS的解析
Description
A city is represented as a bi-directional connected graph with n vertices where each vertex is labeled from 1 to n (inclusive). The edges in the graph are represented as a 2D integer array edges, where each edges[i] = [ui, vi] denotes a bi-directional edge between vertex ui and vertex vi. Every vertex pair is connected by at most one edge, and no vertex has an edge to itself. The time taken to traverse any edge is time minutes.
Each vertex has a traffic signal which changes its color from green to red and vice versa every change minutes. All signals change at the same time. You can enter a vertex at any time, but can leave a vertex only when the signal is green. You cannot wait at a vertex if the signal is green.
The second minimum value is defined as the smallest value strictly larger than the minimum value.
- For example the second minimum value of [2, 3, 4] is 3, and the second minimum value of [2, 2, 4] is 4.
Given n, edges, time, and change, return the second minimum time it will take to go from vertex 1 to vertex n.
Notes:
You can go through any vertex any number of times, including 1 and n.
You can assume that when the journey starts, all signals have just turned green.
Solution
-
先考虑最短路径:最短路径上一定每个结点最多被访问一次
- 否则可以将重复访问的结点删除
- 这样就得到了一个更短的路径
-
类似的针对于次短路径:次短路径上的每个结点最多被访问两次
- 否则若存在结点访问大于等于3次,删去一次该结点-该结点的路径就得到了一条路径,于是这条路径才有可能称为次短路径
-
下述代码层层推进
- 不变量为每一层。出队为同层所有元素出队,入队为下一层元素入队
- 因此队中元始终具有相同的时间 ’
- 因此外层循环每进行一次,搜索的路径长度加1
int secondMinimum(int n, vector<vector<int>>& edges, int time, int change) {
//先中出单源最短路径
vector<int> visited(n, 2);
queue<int> q;
vector<vector<int>> m(n, vector<int>());
vector<int> log(n, -1);//防止节点重复添加
//保存边
for(auto edge: edges){
m[edge[0] - 1].push_back(edge[1] - 1);
m[edge[1] - 1].push_back(edge[0] - 1);
}
q.push(0);
--visited[0];
int t = 0;
int first = -1;
while (!q.empty()) {
int qsize = q.size();
if(t / change % 2 == 1)
t += change - t % change;
t += time;
while (qsize-- > 0) {
int idx = q.front();
q.pop();
for (int i = 0; i < m[idx].size(); ++i) {
if(t <= log[m[idx][i]] || visited[m[idx][i]] == 0) //小于等于处意味着时间(也就是路径长)是和之前一样的,还要期待下一次再次遇到该结点
continue;
--visited[m[idx][i]];
log[m[idx][i]] = t;
q.push(m[idx][i]);
if (m[idx][i] == n - 1) {
if(first == -1){
first = t;
continue;
}
else
return t;
}
}
}
}
return 0;
}
The K-shortest-path Problem
The k shortest path routing problem is a generalization of the shortest path routing problem in a given network. It asks not only about a shortest path but also about next k−1 shortest paths (which may be longer than the shortest path). A variation of the problem is the loopless k shortest paths.