[LeetCode] 1129. Shortest Path with Alternating Colors

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 }

 

LeetCode 题目总结

上一篇:SASS常用语法备忘录


下一篇:9.数组