Opening the reading…
Opening the reading…
GRAPHS › DFS AND BFS ON GRAPHS
Open — the attempt gate is not wired up yet
This editorial is meant to unlock after you have run the problem at least once, with the worked solution behind one further deliberate click. That needs per-learner unlock state nothing stores today, so for now the whole article is open.
Try it yourself first →An ordinary shortest-path search can describe its state with only the current node. Here that is not enough. Reaching node 4 after a red edge is different from reaching node 4 after a blue edge, because the next edge must have the opposite color. The same node can therefore need two separate distances.
Create a state for each pair of a node and the color of the edge used to reach it. From state (u, red), follow only blue edges; from state (u, blue), follow only red edges. Every edge has unit length, so BFS visits these states in nondecreasing path length and the first visit to a state is its shortest valid distance.
Node 0 has no previous edge, so its first edge may be either color. Starting both states at distance 0 represents that freedom: one state permits a blue first edge and the other permits a red first edge. At the end, a node may be reachable with either final color, so its answer is the smaller of the two state distances.
| MEASURE | BOUND | WHY |
|---|---|---|
| Time | O(n + m) | There are 2n possible states. Each state is settled at most once, and every adjacency entry is inspected when its source state is removed, so no edge entry is scanned more than twice for the two possible last colors. |
| Space | O(n + m) | The adjacency lists store m edge entries, while the distance table and queue store O(n) states. The returned answer has length n and is required output, so it is excluded from the extra-space bound. The bound is largest when the input contains all its allowed edge entries. |
#include <algorithm>
#include <queue>
#include <utility>
#include <vector>
using namespace std;
class Solution {
public:
vector<int> shortestAlternatingPaths(
int n,
vector<vector<int>>& redEdges,
vector<vector<int>>& blueEdges
) {
vector<vector<pair<int, int>>> adj(n);
for (const auto& edge : redEdges) {
adj[edge[0]].push_back({edge[1], 0});
}
for (const auto& edge : blueEdges) {
adj[edge[0]].push_back({edge[1], 1});
}
vector<vector<int>> dist(n, vector<int>(2, -1));
queue<pair<int, int>> q;
dist[0][0] = 0;
dist[0][1] = 0;
q.push({0, 0});
q.push({0, 1});
while (!q.empty()) {
auto [u, lastColor] = q.front();
q.pop();
for (auto [v, color] : adj[u]) {
if (color == lastColor) {
continue;
}
if (dist[v][color] != -1) {
continue;
}
dist[v][color] = dist[u][lastColor] + 1;
q.push({v, color});
}
}
vector<int> answer(n, -1);
for (int node = 0; node < n; ++node) {
if (dist[node][0] != -1) {
answer[node] = dist[node][0];
}
if (dist[node][1] != -1) {
if (answer[node] == -1) {
answer[node] = dist[node][1];
} else {
answer[node] = min(answer[node], dist[node][1]);
}
}
}
return answer;
}
};The key indexing choice is dist[v][color]. The color of the edge just taken becomes the last color for the next state, so the following iteration can reject edges with the same color. The condition dist[v][color] != -1 is also state-specific: reaching v after red does not mark reaching v after blue as visited.