Skip to main content

1466. Reordered Routes

Reorder Routes to Make All Paths Lead to the City Zero

Quite an interesting problem. It asks us in a directed graph:

what's the minimum number of directed edges to flip so that every city can reach city 0?

Given to us are nn cities and only n1n - 1 edges, so there will be no cycles.

What Does a Graph Look Like If Every City Can Reach City 0?

It must be that when we start searching from city 0,

all edges connected to city 0 point into city 0.

City 0 has no outgoing edges at all. Then:

I. Suppose an incoming edge of city 0 comes from city ii.

Then the only outgoing edge of city ii must lead to city 00.

As mentioned earlier, this graph contains nn nodes and n1n - 1 edges.

Thus, city 0 has no outgoing edges, while every other city has exactly one outgoing edge.

II. Suppose an incoming edge of city ii comes from city jj.

Then the only outgoing edge of city jj must lead to...yes: city ii.

The reason is the exact same as in Part I.

III. Suppose an incoming edge of city jj comes from city kk, so...

Recursive Relationship of I, II, and III

I believe you have already noticed that I, II, and III are recursive.

But this recursive relationship doesn't have to require DFS in this problem.

BFS can also handle this recursive relationship easily.

Keep reading and you'll see why. 😁

Temporarily Ignore Original Edges' Directions

We prepare a FIFO queue.

Initially, queue contains only city 0, meaning that we start from city 0.

As long as queue isn't empty, we:

remove city ii from queue's front and mark it as visited.

Then examine every edge connected to city ii.

As long as city jj, on the other end of this under-examination edge,

hasn't been visited, we push city jj into queue.

At the same time, we check direction of the edge between city ii and jj.

If this edge points from city ii to jj,

it means this edge must be reversed, so we raise reversal count by one.

from collections import deque


def find_min_reorders(n: int, connections: list[list[int]]) -> int:
src_nodes: list[list[int]] = [[] for _ in range(n)] # Each node's source nodes.
tgt_nodes: list[list[int]] = [[] for _ in range(n)] # Each node's target nodes.

visited: list[bool] = [False] * n

for src_node, tgt_node in connections:
src_nodes[tgt_node].append(src_node)
tgt_nodes[src_node].append(tgt_node)

min_reorders = 0
queue: deque[int] = deque([0]) # Stores nodes.

while queue:
node = queue.popleft()
visited[node] = True

for src_node in src_nodes[node]:
if not visited[src_node]:
queue.append(src_node)

for tgt_node in tgt_nodes[node]:
if not visited[tgt_node]:
min_reorders += 1
queue.append(tgt_node)

return min_reorders

BFS_Efficiency

Every node is visited exactly once, and we also need to track whether each node has been visited.

Both time and space complexity are O(n)O(n).