“习惯是很难打破的,谁不能把它从窗户里抛出去,只能一步一步地哄着它从楼梯上走下来。”——马克·吐温
题目
给你一个二维数组 edges
表示一个 n
个点的无向图,其中 edges[i] = [ui, vi, lengthi]
表示节点 ui
和节点 vi
之间有一条需要 lengthi
单位时间通过的无向边。
同时给你一个数组 disappear
,其中 disappear[i]
表示节点 i
从图中消失的时间点,在那一刻及以后,你无法再访问这个节点。
注意,图有可能一开始是不连通的,两个节点之间也可能有多条边。
请你返回数组 answer
,answer[i]
表示从节点 0
到节点 i
需要的 最少 单位时间。如果从节点 0
出发 无法 到达节点 i
,那么 answer[i]
为 -1
。
难度:中等
分析
此题求的就是图中一点到其他点的最短距离,故应当使用Dijkstra算法。应当注意的有两点:图中的两个节点之间可能有多条边,所以要用最短的边或所有边更新;节点有消失的时间,可以等同地理解为最短距离大于等于消失时间则该节点无法到达,也无法用该节点更新其他节点。Dijkstra算法每次需要选出未确定最短距离的节点中距离最小的节点,由于本题数据量较大,需要使用堆。在C++中则使用priority_queue(优先队列),优先队列的自定义排序较为麻烦,可以在队列中存入pair类型,默认以pair中的第一个值排序,即将距离存入第一个值。
解答
class Solution {
public:
vector<int> minimumTime(int n, vector<vector<int>>& edges, vector<int>& disappear) {
vector<vector<vector<int>>> links(n);
for (auto& v:edges){
//无向边
links[v[0]].push_back({v[1],v[2]});
links[v[1]].push_back({v[0],v[2]});
}
vector<int> visited(n),cost(n,INT_MAX);
cost[0]=0;
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> q; //first距离 second节点
q.push(make_pair(0,0));
while (!q.empty()){
int x=q.top().second;
q.pop();
if (visited[x]==1){
continue;
}
visited[x]=1;
if (cost[x]>=disappear[x]){
cost[x]=INT_MAX; //该节点已消失
continue;
}
for (auto& v:links[x]){
if (visited[v[0]]==0&&cost[x]+v[1]<cost[v[0]]){
cost[v[0]]=cost[x]+v[1];
q.push(make_pair(cost[v[0]],v[0]));
}
}
}
for (int i=0;i<n;i++){
if (cost[i]==INT_MAX){
cost[i]=-1;
}
}
return cost;
}
};