题目来源:
https://leetcode-cn.com/problems/second-minimum-time-to-reach-destination/
思路: 用两个距离数组,记录出发点到各点的距离
其中dis[i][0] 记录最短距离,dis[i][1]记录(严格)次短距离
同时维护dis[i][0]和dis[i][1]即可
如何维护?
我们从队列中取到一个点时,先判断他是否已经计算出次短距离了,如果是就直接抛弃, 然后判断如果他已经被访问过一次(既,已经计算出最短距离) , 判断它的最短距离和当前距离是否相同,相同则不符合严格短的定义,也抛弃
通过上述过滤后,就可以得到正常进行更新的节点了!
class Solution {
public:
struct node{
int p,t;
};
vector<int> G[10010];
map<int,int> vis;
int dis[10010][2];
int secondMinimum(int n, vector<vector<int>>& edges, int time, int change) {
memset(dis,-1,sizeof(dis));
for(auto &it:edges){
G[it[0]].push_back(it[1]);
G[it[1]].push_back(it[0]);
}
queue<node> q;
q.push((node){1,0});
while(q.size()){
auto ft=q.front();
q.pop();
if(vis[ft.p]>=2)
// 这个点已经被访问过两次了,可以被抛弃
continue ;
if(vis[ft.p]==1&&dis[ft.p][0]==ft.t)
// 只访问了一次,但当前拿到的点不是严格第二小点
continue ;
// 记录该点的dis,访问次数
dis[ft.p][vis[ft.p]++]=ft.t;
// 将该点的邻居节点入队
for(auto it:G[ft.p]) q.push((node){it,ft.t+1});
}
// 计算时间
int t=dis[n][1];
int ans=0;
while(--t){
ans+=time;
if((ans/change)%2){
ans+=(change-ans%change);
}
}
return ans+time;
}
};