力扣 2039. 网络空闲的时刻

题目来源:https://leetcode-cn.com/problems/the-time-when-the-network-becomes-idle/

大致题意:
给 n 个节点(编号0 ~ n-1)表示路由器节点,一个二维数组表示相连的节点,一个数组表示每个节点的耐心时间
用 0 节点表示服务器,从 0 秒开始,所有路由器向服务器发送消息,每秒消息只能移动到相邻节点,服务器收到消息后原路返回给节点。每秒开始时,路由器都检查是否收到回复,若没有且当前时间超过了耐心时间,那么重新发送消息;若收到了则不再发送消息
假设消息发送都经过最优路径,求最短在第几秒时,整个网络没有消息

思路

遍历求出每个路由器的消息在网络上的时间,取最长的那个时间 + 1 即为所求秒数

因为需要发送时间尽可能地短,所以消息都经过最短路径发送,这也就是一个边权值相同的最短路径问题,于是可以用 BFS

BFS
  1. 求出每个节点相连的边
  2. 以 0 为源点,开始 BFS
  3. 对于搜索的每个节点,求出其消息在网络中滞留的时间,并统计最大值
  4. 最大值 + 1 即为网络上没有消息的时间

节点消息在网络上滞留的时间为:

  • 节点与源点的最短路径长度 * 2 + 节点最后一次发送消息的时间

使用 time 表示节点与源点的最短路径长度 * 2,使用 p 表示该节点对应的耐心时间,则有:

  • 若 time % p = 0,那么可以先求出重发次数:time / p,因为每秒开始时先检查是否有回复,所以在 time 秒时没有发送消息,那么最后一次发送消息的时间为(time / p - 1) * p
  • 否则,其为 重发次数 * p,即 time / p * p

    public int networkBecomesIdle(int[][] edges, int[] patience) {
        Set<Integer> vis = new HashSet<>(); // 标记访问过的节点
        Map<Integer, List<Integer>> map = new HashMap<>();  // 存每个节点相连的节点
        Queue<int[]> queue = new ArrayDeque<>();    // BFS 的队列
        int n = patience.length;
        // 遍历获取所有节点的相邻节点
        for (int[] edge : edges) {
            int x = edge[0];
            int y = edge[1];
            List<Integer> xList = map.getOrDefault(x, new ArrayList<>());
            xList.add(y);
            map.put(x, xList);
            List<Integer> yList = map.getOrDefault(y, new ArrayList<>());
            yList.add(x);
            map.put(y, yList);
        }
        // 源点入队
        // 两个值,第一个表示节点编号,第二个表示其与源点的最短距离
        queue.offer(new int[]{0, 0});
        vis.add(0);
        int ans = Integer.MIN_VALUE;
        while (!queue.isEmpty()) {
            // 出队
            int[] cur = queue.poll();
            // 获取节点
            int x = cur[0];
            if (x != 0) {
                // 获取最短的来回时间
                int curTime = cur[1] * 2;
                // 求其消息在网络上的滞留时间
                if (curTime % patience[x] == 0) {
                    curTime += (curTime / patience[x] - 1) * patience[x];
                } else {
                    curTime += (curTime / patience[x]) * patience[x];
                }
                // 更新最大值
                ans = Math.max(ans, curTime);
            }
            List<Integer> list = map.get(x);
            // 将相邻未访问的点入队列
            for (int to : list) {
                if (!vis.contains(to)) {
                    vis.add(to);
                    queue.offer(new int[]{to, cur[1] + 1});
                }
            }
        }
        return ans + 1;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三更鬼

谢谢老板!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值