到达目的地的第二短时间

城市用一个 双向连通 图表示,图中有 n 个节点,从 1 到 n 编号(包含 1 和 n)。图中的边用一个二维整数数组 edges 表示,其中每个 edges[i] = [ui, vi] 表示一条节点 ui 和节点 vi 之间的双向连通边。每组节点对由 最多一条 边连通,顶点不存在连接到自身的边。穿过任意一条边的时间是 time 分钟。

每个节点都有一个交通信号灯,每 change 分钟改变一次,从绿色变成红色,再由红色变成绿色,循环往复。所有信号灯都 同时 改变。你可以在 任何时候 进入某个节点,但是 只能 在节点 信号灯是绿色时 才能离开。如果信号灯是  绿色 ,你 不能 在节点等待,必须离开。

第二小的值 是 严格大于 最小值的所有值中最小的值。

例如,[2, 3, 4] 中第二小的值是 3 ,而 [2, 2, 4] 中第二小的值是 4 。
给你 n、edges、time 和 change ,返回从节点 1 到节点 n 需要的 第二短时间 。

注意:

你可以 任意次 穿过任意顶点,包括 1 和 n 。
你可以假设在 启程时 ,所有信号灯刚刚变成 绿色 。
 

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/second-minimum-time-to-reach-destination
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
    public int secondMinimum(int n, int[][] edges, int time, int change) {
        //定义一个HashMap集合,建图
         Map<Integer, List<Integer>> edgeMap = new HashMap<>();
        int min = -1;
        for(int i = 0; i < edges.length; ++i) {
            edgeMap.putIfAbsent(edges[i][0], new ArrayList<>());
            edgeMap.putIfAbsent(edges[i][1], new ArrayList<>());
            edgeMap.get(edges[i][0]).add(edges[i][1]);
            edgeMap.get(edges[i][1]).add(edges[i][0]);
        }
        //维护最短路和次短路
        int[] visit = new int[n + 1];
        Arrays.fill(visit, 2);

        Queue<int[]> queue = new LinkedList<>();
        // 第一位节点位置,第二位存当前走了多久时间
        queue.add(new int[]{1, 0});
        while (!queue.isEmpty()) {
            int size = queue.size();
            boolean[] nextVisit = new boolean[n + 1];
            for(int i = 0; i < size; ++i) {
                int[] cur = queue.poll();
                if (visit[cur[0]] == 0) continue;
                if (cur[0] == n) {
                    if (min == -1) min = cur[1];
                    else if (cur[1] > min) return cur[1];
                }
                visit[cur[0]]--;
                if ((cur[1] / change) % 2 == 1) cur[1] = (cur[1] / change + 1) * change;
                List<Integer> nextPoints = edgeMap.get(cur[0]);
                for(int j = 0; j < nextPoints.size(); ++j) {
                    if (nextVisit[nextPoints.get(j)]) continue;
                    nextVisit[nextPoints.get(j)] = true;
                    queue.add(new int[]{nextPoints.get(j), cur[1] + time});
                }
            }
        }
        return -1;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值