LEECODE(网络延迟时间)

题目描述

有 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;    
};

后续优化

可以优先访问延迟最小的节点(使用优先队列存储),而不是按照深度逐一访问,在某些场景下可以降低遍历和修改的次数

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值