There are n
cities numbered from 0
to n - 1
and n - 1
roads such that there is only one way to travel between two different cities (this network form a tree). Last year, The ministry of transport decided to orient the roads in one direction because they are too narrow.
Roads are represented by connections
where connections[i] = [ai, bi]
represents a road from city ai
to city bi
.
This year, there will be a big event in the capital (city 0
), and many people want to travel to this city.
Your task consists of reorienting some roads such that each city can visit the city 0
. Return the minimum number of edges changed.
It's guaranteed that each city can reach city 0
after reorder.
Example 1:
Input: n = 6, connections = [[0,1],[1,3],[2,3],[4,0],[4,5]] Output: 3 Explanation: Change the direction of edges show in red such that each node can reach the node 0 (capital).
Example 2:
Input: n = 5, connections = [[1,0],[1,2],[3,2],[3,4]] Output: 2 Explanation: Change the direction of edges show in red such that each node can reach the node 0 (capital).
Example 3:
Input: n = 3, connections = [[1,0],[2,0]] Output: 0
Constraints:
2 <= n <= 5 * 104
connections.length == n - 1
connections[i].length == 2
0 <= ai, bi <= n - 1
ai != bi
The problem presents a directed graph representing roads between cities. The goal is to find the minimum number of road direction changes needed to ensure all cities can reach city 0 (the capital). The graph is a tree, meaning there's exactly one path between any two cities.
Both Depth-First Search (DFS) and Breadth-First Search (BFS) efficiently solve this problem. The core idea is to build an undirected graph from the input connections
, and then traverse the graph from city 0, counting the number of edges that need their direction reversed to point towards city 0.
Graph Representation: The input connections
is used to construct an adjacency list. Each node (city) maintains a list of its neighbors, along with a flag indicating whether the edge to that neighbor is initially oriented towards or away from the current node (0 or 1, respectively).
Traversal: A depth-first search (DFS) or breadth-first search (BFS) algorithm starts at city 0. During the traversal, each visited edge is checked. If the edge's orientation is initially away from city 0, the counter for required direction changes is incremented.
Counting Changes: The traversal ensures that all reachable cities are visited. The final count represents the minimum number of edge direction changes.
Both DFS and BFS solutions have a time complexity of O(N), where N is the number of cities. This is because each edge and node in the tree is visited exactly once.
The space complexity for both algorithms is O(N) to store the adjacency list (graph) and the visited set (or queue in BFS). In the worst case, the recursion depth in DFS could be O(N), leading to a space complexity of O(N) for the call stack.
Here's the Python code implementation using both DFS and BFS:
DFS:
from collections import deque
class Solution:
def minReorder(self, n: int, connections: List[List[int]]) -> int:
graph = [[] for _ in range(n)] # Adjacency list
for u, v in connections:
graph[u].append((v, 1)) # (neighbor, direction_flag: 1 if u->v, 0 if v->u)
graph[v].append((u, 0))
visited = set()
changes = 0
def dfs(node):
nonlocal changes
visited.add(node)
for neighbor, direction in graph[node]:
if neighbor not in visited:
changes += direction # Increment if initially away from city 0
dfs(neighbor)
dfs(0) # Start DFS from city 0
return changes
BFS:
from collections import deque
class Solution:
def minReorder(self, n: int, connections: List[List[int]]) -> int:
graph = [[] for _ in range(n)]
for u, v in connections:
graph[u].append((v, 1))
graph[v].append((u, 0))
queue = deque([0])
visited = {0}
changes = 0
while queue:
node = queue.popleft()
for neighbor, direction in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
changes += direction
return changes
The code in other languages (Java, C++, Go, TypeScript, Rust) follows a similar structure and logic, adapting syntax and data structures as needed. The core algorithm (DFS or BFS) remains the same, with the same time and space complexities.