有 N
个网络节点,标记为 1
到 N
。
给定一个列表 times
,表示信号经过有向边的传递时间。 times[i] = (u, v, w)
,其中 u
是源节点,v
是目标节点, w
是一个信号从源节点传递到目标节点的时间。
现在,我们向当前的节点 K
发送了一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1
。
注意:
N
的范围在[1, 100]
之间。K
的范围在[1, N]
之间。times
的长度在[1, 6000]
之间。- 所有的边
times[i] = (u, v, w)
都有1 <= u, v <= N
且1 <= w <= 100
。
思路:这道题其实就是单源最短路劲的问题(即在图中给定节点K,其他所有节点距离K的距离),主要解法有Dijkstra’s algorithm和Bellman–Ford Algorithm解法。接下来分别说下:
思路一:迪杰斯特拉解法,最常见的解法是不使用任何辅助,类似于BFS每次向外拓展一圈。时间复杂度O(n^2),n表示节点。
参考代码:
class Solution {
public:
int minDistance(vector<bool> &sptSet, vector<int> &dict) {
int minValue = INT_MAX, int_index;
for (int i = 1; i < dict.size(); i++) {
if (!sptSet[i] && dict[i]<= minValue) {
minValue = dict[i]; int_index = i;
}
}
return int_index;
}
int networkDelayTime(vector<vector<int>>& times, int N, int K) {
if (times.empty()) return -1;
vector<vector<int>> ad_matrix(N + 1, vector<int>(N + 1, -1));
for (auto time : times) ad_matrix[time[0]][time[1]] = time[2];
vector<bool> sptSet(N + 1, false);
vector<int> dict(N + 1, INT_MAX);
sptSet[0] = true;
dict[K] = 0;
for (int i = 1; i <= (N - 1); i++) {
int u = minDistance(sptSet, dict);
sptSet[u] = true;
for (int v = 1; v <= N; v++) {
if (!sptSet[v] && dict[u] != INT_MAX && ad_matrix[u][v] != -1 && dict[v] > (dict[u] + ad_matrix[u][v])) {
dict[v] = dict[u] + ad_matrix[u][v];
}
}
}
int res = 0;
for (int i = 1; i <= N; i++) {
if (dict[i] == INT_MAX) return -1;
res = max(res, dict[i]);
}
return res;
}
};
思路二:采用了最小堆,每次从堆中取出距离最短的节点,时间复杂度为O(vlogv)。
参考代码:
class Solution {
public:
struct networkDelayTimeCmp {
bool operator()(const pair<int, int> &a, const pair<int, int> &b) {
return a.second > b.second;
}
};
unordered_map<int, vector<vector<int>>> make_graph(vector<vector<int>>& times, int N) {
unordered_map<int, vector<vector<int>>> res;
for (auto node : times) {
if (res.find(node[0]) == res.end()) res[node[0]] = { {node[1],node[2]} };
else {
vector<vector<int>> old = res[node[0]];
old.push_back({ node[1],node[2] });
res[node[0]] = old;
}
}
return res;
}
int networkDelayTime(vector<vector<int>>& times, int N, int K) {
if (times.empty()) return -1;
priority_queue<pair<int, int>, vector<pair<int, int>>, networkDelayTimeCmp> q;
unordered_map<int, vector<vector<int>>> map = make_graph(times, N);
vector<int> dict(N+1,INT_MAX);
dict[K] = 0;
q.push({K,0});
while (!q.empty()) {
auto closest = q.top(); q.pop();
if (map.find(closest.first) != map.end()) {
for (auto neibors : map[closest.first]) {
int v = neibors[0];
int weight = neibors[1];
int u = closest.first;
if ((long)(dict[v]) > (long)(dict[u] + weight)) {
dict[v] = (dict[u] + weight);
q.push({v,dict[v]});
}
}
}
}
int res = 0;
for (int i = 1; i <= N;i++) {
if (dict[i]==INT_MAX) {
return -1;
}
res = max(res, dict[i]);
}
return res;
}
};
思路三:最后是bellman算法,时间复杂度为O(vloge)(v表示节点,e表示边)
参考代码:
class Solution {
public:
int networkDelayTime(vector<vector<int>>& times, int N, int K) {
if (times.empty()) return -1;
vector<int> dict(N + 1, INT_MAX);
dict[K]=0;
for (int i = 1; i < N; i++) {
for (auto time : times) {
int u = time[0], v = time[1], w = time[2];
if (dict[u] != INT_MAX && dict[v] > (dict[u] + w)) {
dict[v] = dict[u] + w;
}
}
}
int res = 0;
for (int i = 1; i <= N; i++) {
if (dict[i] == INT_MAX) return -1;
res = max(res, dict[i]);
}
return res;
}
};