There is a simple directed graph with n nodes labeled from 0 to n - 1. The graph would form a tree if its edges were bi-directional.
You are given an integer n and a 2D integer array edges, where edges[i] = [ui, vi] represents a directed edge going from node ui to node vi.
An edge reversal changes the direction of an edge, i.e., a directed edge going from node ui to node vi becomes a directed edge going from node vi to node ui.
For every node i in the range [0, n - 1], your task is to independently calculate the minimum number of edge reversals required so it is possible to reach any other node starting from node i through a sequence of directed edges.
Return an integer array answer, where answer[i] is the minimum number of edge reversals required so it is possible to reach any other node starting from node i through a sequence of directed edges.
Example 1:

Input: n = 4, edges = [[2,0],[2,1],[1,3]] Output: [1,1,0,2] Explanation: The image above shows the graph formed by the edges. For node 0: after reversing the edge [2,0], it is possible to reach any other node starting from node 0. So, answer[0] = 1. For node 1: after reversing the edge [2,1], it is possible to reach any other node starting from node 1. So, answer[1] = 1. For node 2: it is already possible to reach any other node starting from node 2. So, answer[2] = 0. For node 3: after reversing the edges [1,3] and [2,1], it is possible to reach any other node starting from node 3. So, answer[3] = 2.
Example 2:

Input: n = 3, edges = [[1,2],[2,0]] Output: [2,0,1] Explanation: The image above shows the graph formed by the edges. For node 0: after reversing the edges [2,0] and [1,2], it is possible to reach any other node starting from node 0. So, answer[0] = 2. For node 1: it is already possible to reach any other node starting from node 1. So, answer[1] = 0. For node 2: after reversing the edge [1, 2], it is possible to reach any other node starting from node 2. So, answer[2] = 1.
Constraints:
2 <= n <= 105edges.length == n - 1edges[i].length == 20 <= ui == edges[i][0] < n0 <= vi == edges[i][1] < nui != viWhen you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The core idea is to try every possible combination of reversing edges in the graph. For each combination, we check if starting from a specific node, we can reach all other nodes. We choose the combination that requires the fewest edge reversals to achieve this reachability.
Here's how the algorithm would work step-by-step:
def min_edge_reversals_brute_force(num_nodes, edges):
min_reversals = float('inf')
# Iterate through all possible combinations of edge reversals.
for i in range(2**len(edges)):
reversed_edges_indices = []
for j in range(len(edges)):
if (i >> j) & 1:
reversed_edges_indices.append(j)
# Create a modified graph with the reversed edges.
modified_edges = []
for index, (source_node, dest_node) in enumerate(edges):
if index in reversed_edges_indices:
modified_edges.append((dest_node, source_node))
else:
modified_edges.append((source_node, dest_node))
# Check reachability from each node.
for start_node in range(num_nodes):
# Check if all nodes are reachable from the start node.
reachable_nodes = set()
queue = [start_node]
reachable_nodes.add(start_node)
while queue:
current_node = queue.pop(0)
for source_node, dest_node in modified_edges:
if source_node == current_node and dest_node not in reachable_nodes:
reachable_nodes.add(dest_node)
queue.append(dest_node)
# If all nodes are reachable, update the minimum reversals.
if len(reachable_nodes) == num_nodes:
# Calculate the number of reversals for this combination.
num_reversals = len(reversed_edges_indices)
min_reversals = min(min_reversals, num_reversals)
if min_reversals == float('inf'):
return -1 # Indicate no solution if no configuration makes all nodes reachable.
return min_reversalsThe problem asks to find the fewest arrow flips needed to make all points reachable from a starting point. This is solved efficiently by focusing on counting the 'wrong way' edges and avoiding redundant calculations using a clever traversal strategy.
Here's how the algorithm would work step-by-step:
def min_edge_reversals(number_of_nodes, edges):
graph = [[] for _ in range(number_of_nodes)]
for start_node, end_node in edges:
graph[start_node].append((end_node, 0))
graph[end_node].append((start_node, 1))
minimum_reversals = float('inf')
for start_node in range(number_of_nodes):
reversals_needed = 0
visited = [False] * number_of_nodes
queue = [(start_node, 0)]
visited[start_node] = True
# Traverse the graph from the current start node.
while queue:
current_node, current_reversals = queue.pop(0)
reversals_needed += current_reversals
for neighbor, edge_direction in graph[current_node]:
if not visited[neighbor]:
# Add neighbors to queue;mark visited.
visited[neighbor] = True
queue.append((neighbor, edge_direction))
# We take the minimum reversals across all nodes
minimum_reversals = min(minimum_reversals, reversals_needed)
return minimum_reversals| Case | How to Handle |
|---|---|
| Empty graph (n=0) | Return an empty array since there are no nodes to reach. |
| Single node graph (n=1) | Return an array containing only 0, as the node is reachable from itself. |
| Graph is a tree (no cycles) | The DFS/BFS should correctly traverse the tree and count reversals. |
| Graph is disconnected | If the graph is disconnected and not all nodes are reachable, it should either return -1 or an appropriate error based on problem constraints, or calculate the reachable nodes from each initial node. |
| Graph is a complete graph (every node connected to every other) | This represents the maximum possible number of edges and requires efficient traversal to avoid time limit exceeded. |
| Edges contain duplicate connections (e.g., (0,1) and (0,1) exist) | The graph representation (adjacency list/matrix) should handle or prevent duplicate edges to avoid overcounting. |
| All edges point away from node 0 | This will likely result in the maximum number of edge reversals needed and tests the algorithm's ability to handle worst-case scenarios. |
| All edges point towards node 0 | This requires no edge reversals and verifies the algorithm's correctness in the best-case scenario. |