Consider a directed graph, with nodes labelled 0, 1, ..., n-1
. In this graph, each edge is either red or blue, and there could be self-edges or parallel edges.
Each [i, j]
in red_edges
denotes a red directed edge from node i
to node j
. Similarly, each [i, j]
in blue_edges
denotes a blue directed edge from node i
to node j
.
Return an array answer
of length n
, where each answer[X]
is the length of the shortest path from node 0
to node X
such that the edge colors alternate along the path (or -1
if such a path doesn't exist).
Example 1:
Input: n = 3, red_edges = [[0,1],[1,2]], blue_edges = [] Output: [0,1,-1]
Example 2:
Input: n = 3, red_edges = [[0,1]], blue_edges = [[2,1]] Output: [0,1,-1]
Example 3:
Input: n = 3, red_edges = [[1,0]], blue_edges = [[2,1]] Output: [0,-1,-1]
Example 4:
Input: n = 3, red_edges = [[0,1]], blue_edges = [[1,2]] Output: [0,1,2]
Example 5:
Input: n = 3, red_edges = [[0,1],[0,2]], blue_edges = [[1,0]] Output: [0,1,1]
Constraints:
1 <= n <= 100
red_edges.length <= 400
blue_edges.length <= 400
red_edges[i].length == blue_edges[i].length == 2
0 <= red_edges[i][j], blue_edges[i][j] < n
颜色交替的最短路径。
在一个有向图中,节点分别标记为 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。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shortest-path-with-alternating-colors
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这是一道图论的题。题目说了是一个有向图并且找的是一条最短的,红蓝交替的从0去到其他所有节点的路径,那么思路应该是BFS。既然是图的题,那么我们一开始要做的依然是把图创建起来。这道题比较特殊的地方在于因为有可能两个node之间既有红色边又有蓝色边,所以我们这里选择创建的是邻接矩阵,矩阵里面如果放的是 -n 表示两个点不相连;矩阵里面如果放的是 1 表示两个点之间有一条红色的边,-1 表示有一条蓝色的边,红蓝都有我们用0表示。
既然是BFS,那么queue里面一开始我们放(0, 1)和(0,-1),表示去到0的点有红色和蓝色两种情况。从queue中弹出的时候,我们判断的是从0去到所有其他的点,是否存在一条有效的边同时颜色跟之前的颜色相反。同时这里我们为了防止死循环,需要用一个hashset记录遍历过的点和边的颜色(记录一下之前是通过什么颜色的边访问到某个点的)。
时间O(V + E)
空间O(n) - hashset
Java实现
1 class Solution { 2 public int[] shortestAlternatingPaths(int n, int[][] red_edges, int[][] blue_edges) { 3 int[][] g = new int[n][n]; 4 buildGraph(g, n, red_edges, blue_edges); 5 6 Queue<int[]> queue = new LinkedList<>(); 7 // [node, color] 8 queue.offer(new int[] { 0, 1 }); 9 queue.offer(new int[] { 0, -1 }); 10 int step = 0; 11 int[] res = new int[n]; 12 Arrays.fill(res, Integer.MAX_VALUE); 13 res[0] = 0; 14 15 // 记录某个点是否以某种颜色的方式visited过 16 Set<String> visited = new HashSet<>(); 17 while (!queue.isEmpty()) { 18 int size = queue.size(); 19 step++; 20 for (int i = 0; i < size; i++) { 21 int[] cur = queue.poll(); 22 int node = cur[0]; 23 int color = cur[1]; 24 int oppoColor = -color; 25 26 for (int j = 1; j < n; j++) { 27 if (g[node][j] == oppoColor || g[node][j] == 0) { 28 if (!visited.add(j + "" + oppoColor)) { 29 continue; 30 } 31 queue.offer(new int[] { j, oppoColor }); 32 res[j] = Math.min(res[j], step); 33 } 34 } 35 } 36 } 37 38 for (int i = 1; i < n; i++) { 39 if (res[i] == Integer.MAX_VALUE) { 40 res[i] = -1; 41 } 42 } 43 return res; 44 } 45 46 private void buildGraph(int[][] g, int n, int[][] red_edges, int[][] blue_edges) { 47 for (int i = 0; i < n; i++) { 48 // 初始化为-n 49 Arrays.fill(g[i], -n); 50 } 51 52 // 红色边标记成1 53 for (int[] e : red_edges) { 54 int from = e[0]; 55 int to = e[1]; 56 g[from][to] = 1; 57 } 58 59 for (int[] e : blue_edges) { 60 int from = e[0]; 61 int to = e[1]; 62 // 如果有红色边了,标记成0 63 // 如果没有红色边,标记成-1 64 if (g[from][to] == 1) { 65 g[from][to] = 0; 66 } else { 67 g[from][to] = -1; 68 } 69 } 70 } 71 }