class Solution:
def minReorder(self, n, connections):
from collections import defaultdict, deque
# Build graph: store direction by sign (u->v is positive, v->u is negative)
graph = defaultdict(list)
for u, v in connections:
graph[u].append((v, 1)) # original direction u -> v
graph[v].append((u, 0)) # reverse direction v -> u
visited = set()
queue = deque([0])
visited.add(0)
changes = 0
while queue:
node = queue.popleft()
for neighbor, needs_change in graph[node]:
if neighbor not in visited:
changes += needs_change
visited.add(neighbor)
queue.append(neighbor)
return changes
class Solution {
public:
int minReorder(int n, vector<vector<int>>& connections) {
vector<vector<pair<int,bool>>> graph(n);
for (auto& conn : connections) {
graph[conn[0]].push_back({conn[1], true}); // original direction
graph[conn[1]].push_back({conn[0], false}); // reverse direction
}
vector<bool> visited(n, false);
queue<int> q;
q.push(0);
visited[0] = true;
int changes = 0;
while (!q.empty()) {
int node = q.front(); q.pop();
for (auto& [neighbor, needsChange] : graph[node]) {
if (!visited[neighbor]) {
changes += needsChange;
visited[neighbor] = true;
q.push(neighbor);
}
}
}
return changes;
}
};
class Solution {
public int minReorder(int n, List<List<Integer>> connections) {
List<List<int[]>> graph = new ArrayList<>();
for (int i = 0; i < n; i++) graph.add(new ArrayList<>());
for (List<Integer> conn : connections) {
int u = conn.get(0), v = conn.get(1);
graph.get(u).add(new int[]{v, 1}); // original direction
graph.get(v).add(new int[]{u, 0}); // reverse direction
}
boolean[] visited = new boolean[n];
Queue<Integer> queue = new LinkedList<>();
queue.offer(0);
visited[0] = true;
int changes = 0;
while (!queue.isEmpty()) {
int node = queue.poll();
for (int[] edge : graph.get(node)) {
int neighbor = edge[0], needsChange = edge[1];
if (!visited[neighbor]) {
changes += needsChange;
visited[neighbor] = true;
queue.offer(neighbor);
}
}
}
return changes;
}
}
var minReorder = function(n, connections) {
const graph = Array.from({length: n}, () => []);
for (const [u, v] of connections) {
graph[u].push([v, 1]); // original direction
graph[v].push([u, 0]); // reverse direction
}
const visited = new Array(n).fill(false);
let changes = 0;
const queue = [0];
visited[0] = true;
while (queue.length) {
const node = queue.shift();
for (const [neighbor, needsChange] of graph[node]) {
if (!visited[neighbor]) {
changes += needsChange;
visited[neighbor] = true;
queue.push(neighbor);
}
}
}
return changes;
};
Given n
cities numbered from 0
to n-1
and a list of connections
where each connection is a directed road [a, b]
from city a
to city b
, you are to reorient some of these roads so that all cities can reach city 0
via a path following the direction of the roads.
Your task is to find the minimum number of roads that need to be changed in direction so that, for every city, there exists a path following the direction of the roads that leads to city 0
.
Constraints:
n-1
connections, so the network is a tree (connected, no cycles).
At first glance, the brute-force approach would be to try all combinations of road direction changes and check if every city can reach city 0
. However, this would be highly inefficient, especially for larger values of n
.
Instead, let's rethink the problem: since the network forms a tree, there is exactly one unique path from every city to city 0
. The only thing that can prevent a city from reaching 0
is if one or more roads along its unique path are pointing away from 0
.
So, if we can traverse the tree starting from city 0
and count how many roads are "pointing the wrong way" (i.e., away from 0
), we can determine the minimum number of changes needed. This leads us to a traversal-based solution.
We can use either BFS or DFS starting from city 0
to traverse the tree. The key idea is to represent the graph in such a way that, for each edge, we can quickly determine if it needs to be reversed.
[a, b]
, add (b, 1)
to a
's list (indicating the original direction) and (a, 0)
to b
's list (indicating the reverse direction).
0
. For each neighboring city, check the direction:
0
), increment the change counter because we need to reverse this road.0
), no change is needed.We use a hash map (or array of lists) for fast lookups, and a queue or stack for traversal. The overall process is efficient and leverages the tree structure.
Let's consider n = 6
and connections = [[0,1],[1,3],[2,3],[4,0],[4,5]]
.
Final answer: 3 roads must be reversed.
Brute-force approach: Trying all combinations of road reversals is exponential in the number of connections, i.e., O(2n-1), and is not feasible.
Optimized approach:
The key insight is that the problem reduces to counting the number of roads that point away from city 0
on the unique path from each city to 0
. By traversing the tree starting at 0
and counting such roads, we efficiently compute the minimum number of changes required. The solution leverages properties of trees and adjacency lists, resulting in an elegant and optimal O(n) approach.