题目描述
有 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 且 0 <= w <= 100。
解题思路
1、该问题是一个图问题;
2、 从初始节点(k)开始遍历,采用广度优先的算法;
3、当遍历到一个节点时,如果该节点没有被访问过,则记录访问时间,并把它放到下次遍历的节点中;如果被访问过,但之前记录的访问时间比这次的要大,则更新访问时间,同时也把它放入下次遍历的节点集合中;只有记录的访问时间小于或等于这次的访问时间时,才不做任何操作;
4、直到没有新的节点集合为止;
代码
class Solution {
public:
int networkDelayTime(vector<vector<int> >& times, int N, int K) {
initial(times); // initialize m_node2others structure
vector<int> nodes; // from which we begin to reach new nodes
nodes.push_back(K); // initial state
m_node2time.insert(make_pair(K, 0));
while(nodes.size()) {
vector<int> next_nodes;
for(auto parent : nodes) {
if(m_node2others.count(parent) == 0) { // this node can't reach other nodes
continue;
}
auto& others = m_node2others.at(parent);
for(auto& child_w_time : others) {
if(m_node2time.count(child_w_time.first)
&& m_node2time.at(child_w_time.first) <= m_node2time.at(parent) + child_w_time.second) {
continue;
}
next_nodes.push_back(child_w_time.first);
if(m_node2time.count(child_w_time.first)==0) {
m_node2time.insert(make_pair(child_w_time.first, m_node2time.at(parent) + child_w_time.second));
}else {
m_node2time.at(child_w_time.first) = m_node2time.at(parent) + child_w_time.second;
}
}
}
nodes.swap(next_nodes);
}
if(m_node2time.size() != N) {
return -1;
}
int max_time = -1;
for(auto n: m_node2time) {
if(n.second > max_time) {
max_time = n.second;
}
}
return max_time;
}
private:
void initial(const vector<vector<int>>& times) {
for(auto& edge : times) {
assert(edge.size()==3);
m_node2others[edge.at(0)].push_back(make_pair(edge.at(1), edge.at(2)));
}
}
private:
map<int, int> m_node2time; // key is node, value is the minimun time received the signal
map<int/*node1*/, vector<pair<int/*node2*/, int/*transfer time*/> > > m_node2others;
};
后续优化
可以优先访问延迟最小的节点(使用优先队列存储),而不是按照深度逐一访问,在某些场景下可以降低遍历和修改的次数