leetcode 1129. 颜色交替的最短路径

208 阅读2分钟

1. 题目与解析

在一个有向图中,节点分别标记为 0, 1, ..., n-1。图中每条边为红色或者蓝色,且存在自环或平行边。

red_edges 中的每一个 [i, j] 对表示从节点 i 到节点 j 的红色有向边。类似地, blue_edges 中的每一个 [i, j] 对表示从节点 i 到节点 j 的蓝色有向边。

返回长度为 n 的数组 answer,其中 answer[X] 是从节点 0 到节点 X 的红色边和蓝色边交替出现的最短路径的长度。如果不存在这样的路径,那么 answer[x] = -1

可以使用广度优先搜索的方法解题。

首先,需要记录两种颜色的单向图的临接表,以供后期的广度优先搜索使用。

使用广度优先搜索获取从节点 0 到某一节点的两种类型的颜色交替最短路径的长度,广度优先搜索的队列元素由节点编号和节点路径类型组成,初始时节点 0 到节点 x 的两种类型的颜色交替最短路径的长度都是 1,将初始值入队。

之后,针对不同类型的队列,分别进行广度优先搜索,并且维护两个记录单元,分别记录通过红色以及蓝色路径到达到节点x所需要的步数,每一次需要更新的时候,都会触发后驱节点的更新过程。

最后取两者的最小值构成我们需要的答案输出。

2. 题解

class Solution {
    public int[] shortestAlternatingPaths(int n, int[][] redEdges, int[][] blueEdges) {
        Queue<Integer> redQue = new LinkedList<>();
        Queue<Integer> blueQue = new LinkedList<>();
        int[] redList = new int[n];
        int[] blueList = new int[n];
        Map<Integer, List<Integer>> redMap = new HashMap<>();
        Map<Integer, List<Integer>> blueMap = new HashMap<>();
        for (int[] arr: redEdges) {
            if (!redMap.containsKey(arr[0])) {
                redMap.put(arr[0], new ArrayList<>());
            }
            redMap.get(arr[0]).add(arr[1]);
        }
        for (int[] arr: blueEdges) {
            if (!blueMap.containsKey(arr[0])) {
                blueMap.put(arr[0], new ArrayList<>());
            }
            blueMap.get(arr[0]).add(arr[1]);
        }
        Arrays.fill(redList, Integer.MAX_VALUE);
        Arrays.fill(blueList, Integer.MAX_VALUE);

        if (redMap.containsKey(0)) {
            for (int to: redMap.get(0)) {
                redQue.add(to);
                redList[to] = 1;
            }
        }
        if (blueMap.containsKey(0)) {
            for (int to: blueMap.get(0)) {
                blueQue.add(to);
                blueList[to] = 1;
            }          
        }

        while (!redQue.isEmpty() || !blueQue.isEmpty()) {
            while (!redQue.isEmpty()) {
                int poll = redQue.poll();
                if (!blueMap.containsKey(poll)) {
                    continue;
                }
                for (int to: blueMap.get(poll)) {
                    if (blueList[to] > redList[poll] + 1) {
                        blueQue.add(to);
                        blueList[to] = redList[poll] + 1;
                    }
                }
            }
            while (!blueQue.isEmpty()) {
                int poll = blueQue.poll();
                if (!redMap.containsKey(poll)) {
                    continue;
                }
                for (int to: redMap.get(poll)) {
                    if (redList[to] > blueList[poll] + 1) {
                        redQue.add(to);
                        redList[to] = blueList[poll] + 1;
                    }
                }
            }
        }

        int[] ans = new int[n];
        for (int i = 0; i < n; i++) {
            ans[i] = Math.min(redList[i], blueList[i]);
            if (ans[i] == Integer.MAX_VALUE) {
                ans[i] = -1;
            }
        }
        ans[0] = 0;
        return ans;

    }
}