难度:中等。
标签:深度优先搜索,广度优先搜索,图,最短路,堆(优先队列)。
看题解,Dijkstra就没记住过。
使用Dijkstra算法进行求解,求出节点 k到其余所有点的最短路,其中的最大值就是答案。
Dijkstra算法将点分为未确定点和确定点,每次从未确定点中找到与起点k距离最近的点x,然后更新所有未确定点的距离,并将x加入确定点集中。
正确解法:
class Solution {
public:
int networkDelayTime(vector<vector<int>>& times, int n, int k) {
if(times.size() < n - 1)return -1;
const int inf = INT_MAX / 2;
vector<vector<int>> graph(n, vector<int>(n, inf));
for(int i = 0; i < times.size(); ++i){
graph[times[i][0] - 1][times[i][1] - 1] = times[i][2];
}
vector<int> dist(n, inf);
dist[k - 1] = 0;
vector<int> visited(n, 0);
for(int i = 0; i < n; ++i){
// 未确定点中与k距离最小的点
int x = -1;
for(int y = 0; y < n; ++y){
if(!visited[y] && (x == -1 || dist[y] < dist[x])){
x = y;
}
}
visited[x] = 1;
for(int y = 0; y < n; ++y){
dist[y] = min(dist[y], dist[x] + graph[x][y]);
}
}
int ans = *max_element(dist.begin(), dist.end());
return ans >= inf ? -1 : ans;
}
};
结果:
还可以使用小根堆来寻找未确定节点中与起点k距离最近的点。
小跟堆存储pair,second表示当前节点,first表示起点到second所需的时间。每次将时间最小的项p得到,若当前值小于dist[p.second],则用当前节点p.second更新其他p.second可直接到达的节点的距离。
正确解法:
class Solution {
public:
int networkDelayTime(vector<vector<int>>& times, int n, int k) {
if(times.size() < n - 1)return -1;
const int inf = INT_MAX / 2;
vector<vector<pair<int,int>>> graph(n);
for(int i = 0; i < times.size(); ++i){
graph[times[i][0] - 1].emplace_back(times[i][1] - 1, times[i][2]);
}
vector<int> dist(n, inf);
dist[k - 1] = 0;
// pair<起点到达second的时间,节点>
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> q;
q.emplace(0, k - 1);
while(!q.empty()){
auto p = q.top();
q.pop();
int time = p.first, x = p.second;
if(dist[x] < time)continue;
for(auto& e : graph[x]){
int y = e.first, d = dist[x] + e.second;
if(d < dist[y]){
dist[y] = d;
q.emplace(d, y);
}
}
}
int ans = *max_element(dist.begin(), dist.end());
return ans >= inf ? -1 : ans;
}
};
结果: