743. 网络延迟时间
难度中等
有 N 个网络节点,标记为 1 到 N。
给定一个列表 times,表示信号经过有向边的传递时间。 times[i] = (u, v, w),其中 u 是源节点,v 是目标节点, w 是一个信号从源节点传递到目标节点的时间。
现在,我们从某个节点 K 发出一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1。
示例:
输入:times = [[2,1,1],[2,3,1],[3,4,1]], N = 4, K = 2
输出:2
注意:
1. N 的范围在 [1, 100] 之间。
2. K 的范围在 [1, N] 之间。
3. times 的长度在 [1, 6000] 之间。
4. 所有的边 times[i] = (u, v, w) 都有 1 <= u, v <= N 且 0 <= w <= 100。
思路1.0:
广度优先遍历,从起点向外扩散,用一个二维数组来存储节点之间的前驱后继关系。
代码1.0(未过):
struct inferTo {
int target;
int weight;
inferTo() :target(0), weight(0) {}
inferTo(int x, int y) :target(x), weight(y) {}
};
class Solution {
public:
int networkDelayTime(vector<vector<int>>& times, int N, int K) {
vector<vector<inferTo>> adjacency(N + 1, vector<inferTo>());
list<inferTo> list_;
int ans = 0;
int visitNum = 1;
//初始化二维矩阵
for (const auto& i : times) {
adjacency[i[0]].push_back({ i[1],i[2] });
}
//从起点向外广度优先遍历
for (const auto& i : adjacency[K]) {
list_.push_back(i);
}
while (!list_.empty()) {
int distance = INT_MAX;
//找到当前所有能到达目的地的最小距离
for (const auto& i : list_)
distance = min(distance, i.weight);
//减去最小距离
auto be = list_.begin();
for (int len = list_.size(); len > 0; --len) {
(*be).weight -= distance;
//如果减完了,将该点的所有后继节点加入列表list_,并删掉该节点
if ((*be).weight == 0) {
for (const auto& i : adjacency[(*be).target]) {
list_.push_back(i);
}
list_.erase(be++);
visitNum++;
}
//如果没减完,遍历下一个
else
be++;
}
ans += distance;
if (visitNum == N) return ans;
}
if (visitNum != N) return -1;
return ans;
}
};
没考虑到环路的情况,shit!
思路2.0:
通过记录每个节点的前驱个数,并在广度遍历的过程中对其更新,从而来剔除那些已经进入广度优先树的前驱不会重复进入。
思路3.0(已看题解):
Djikstra算法,从所有可选路径中选择最短路径加入图中。具体实现需要如下数据结构:
1)一个二维数组存储每条边的信息,起点,终点,权值
2)一个存储所有节点到起点的最短距离
3)一个存储所有节点是否找到了最短距离
代码2.0:
class Solution {
public:
int networkDelayTime(vector<vector<int>>& times, int n, int K) {
vector<vector<int>> djacency(n + 1, vector<int>(n + 1, INT_MAX));
for (const auto& i : times) {
djacency[i[0]][i[1]] = i[2];
}
vector<long> shortest(n + 1, INT_MAX);
vector<bool> isShortest(n + 1, false);
//起点
shortest[K] = 0;
//
for (int i = 0; i < n - 1; ++i) {
int index = -1; //用于存储当前可选择路径中的最短路径
for (int j = 1; j <= n; ++j) {
if (!isShortest[j] && (index == -1 || shortest[j] < shortest[index])) {
index = j;
}
}
isShortest[index] = true;
//更新shortest值
for (int j = 1; j <= n; ++j) {
shortest[j] = min(shortest[j], djacency[index][j]+shortest[index]);
}
}
int ans = *max_element(shortest.begin() + 1, shortest.end());
return ans == INT_MAX ? -1 : ans;
}
};