I knew it was a tree problem pretty fast but spent way too long trying to brute-force a BFS from every node before accepting that wouldn't scale.
Model the tree as an undirected graph where each original directed edge has cost 0 if traversed in its direction and cost 1 if reversed. Then, for each node, compute the sum of costs to reach all other nodes using two DFS passes (rerooting technique) to avoid O(n^2) recomputation.
Pro tip: Start by explaining the brute-force O(n^2) approach, then optimize with rerooting. This shows you can think from naive to optimal, a key skill at Uber where scalability matters.
Confirm that the tree is directed and that we can reverse any edge. Represent each edge as two directed edges: one with cost 0 (original direction) and one with cost 1 (reverse direction).
For each node, run a DFS/BFS to compute the total cost to reach all other nodes. This gives O(n^2) time, which is correct but inefficient for large n.
First, root the tree arbitrarily (e.g., at node 0) and compute the cost to reach all nodes from the root using a post-order DFS. Then, use a pre-order DFS to compute the answer for each child from its parent's answer by adjusting for the edge between them.
When moving the root from parent u to child v, the cost changes by: if edge u->v exists, subtract 1 from v's subtree cost and add 1 to the rest; if edge v->u exists, add 1 to v's subtree cost and subtract 1 from the rest. Use subtree sizes to compute efficiently.
The two-pass DFS runs in O(n) time and O(n) space, which is optimal. Mention that this handles large inputs typical in production systems.
AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.