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到所有其他結點的最短距離,並且要求路徑必須是紅藍交替,即不能有相同顏色的兩條邊相連。這種遍歷圖求最短路徑的題目的首選解法應該是廣度優先遍歷 Breadth-first Search,就像迷宮遍歷的問題一樣,由於其遍歷的機制,當其第一次到達某個結點時,當前的步數一定是最少的。不過這道題還有一個難點,就是如何保證路徑是紅藍交替的,這就跟以往有些不同了,必須要建立兩個圖的結構,分別保存紅邊和藍邊,為了方便起見,使用一個二維數組,最外層用0表示紅邊,1表示藍邊。內層是一個大小為n的數組,因為有n個結點,數組中的元素是一個 HashSet,因為每個結點可能可以連到多個其他的結點,這個圖的結構可以說是相當的復雜了。接下來就是給圖結構賦值了,分別遍歷紅邊和藍邊的數組,將對應的結點連上,就是將相連的結點加到 HashSet 中。由於到達每個結點可能通過紅邊或者藍邊,所以就有兩個狀態,這里用一個二維的 dp 數組來記錄這些狀態,其中 dp[i][j] 表示最后由顏色i的邊到達結點j的最小距離,除了結點0之外,均初始化為 2n,因為即便是有向圖,到達某個結點的最小距離也不可能大於 2n。由於是 BFS 遍歷,需要用到 queue,這里的 queue 中的元素需要包含兩個信息,當前的結點值,到達該點的邊的顏色,所以初始化時分別將 (0,0) 和 (0,1) 放進去,前一個0表示結點值,后一個表示到達該點的邊的顏色。接下來就可以進行 BFS 遍歷了,進行 while 循環,將隊首元素取出,將結點值 cur 和顏色值 color 取出。由於到達當前結點的邊的顏色是 color,接下來就只能選另一種顏色了,則可以用 1-color 來選另一種顏色,並且在該顏色下遍歷和 cur 相連的所有結點,若其對應的 dp 值仍為 2n,說明是第一次到達該結點,可用當前 dp 值加1來更新其 dp 值,並且將新的結點值與其顏色加入到隊列中以便下次遍歷其相連結點。當循環結束之后,只需要遍歷一次 dp 值,將每個結點值對應的兩個 dp 值中的較小的那個放到結果 res 中即可,注意要進行一下判斷,若 dp 值仍為 2n,說明無法到達該結點,需要換成 -1,參見代碼如下:
class Solution {
public:
vector<int> shortestAlternatingPaths(int n, vector<vector<int>>& red_edges, vector<vector<int>>& blue_edges) {
vector<int> res(n);
vector<vector<int>> dp(2, vector<int>(n));
vector<vector<unordered_set<int>>> graph(2, vector<unordered_set<int>>(n));
for (auto &edge : red_edges) {
graph[0][edge[0]].insert(edge[1]);
}
for (auto &edge : blue_edges) {
graph[1][edge[0]].insert(edge[1]);
}
for (int i = 1; i < n; ++i) {
dp[0][i] = 2 * n;
dp[1][i] = 2 * n;
}
queue<vector<int>> q;
q.push({0, 0});
q.push({0, 1});
while (!q.empty()) {
int cur = q.front()[0], color = q.front()[1]; q.pop();
for (int next : graph[1 - color][cur]) {
if (dp[1 - color][next] == 2 * n) {
dp[1 - color][next] = 1 + dp[color][cur];
q.push({next, 1 - color});
}
}
}
for (int i = 0; i < n; ++i) {
int val = min(dp[0][i], dp[1][i]);
res[i] = val == 2 * n ? -1 : val;
}
return res;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/1129
參考資料:
https://leetcode.com/problems/shortest-path-with-alternating-colors/
https://leetcode.com/problems/shortest-path-with-alternating-colors/discuss/339964/JavaPython-BFS