Implement bidirectional Dijkstra for shortest paths
Company: Citi
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: Medium
Interview Round: Onsite
Quick Answer: This question evaluates proficiency in graph algorithms and algorithm engineering, specifically understanding and implementing bidirectional shortest-path search with appropriate data structures, termination conditions, path reconstruction, and time/space complexity analysis.
Constraints
- 1 <= n <= 10^5
- 0 <= u, v < n
- 0 <= w <= 10^6 (edge weights are non-negative)
- 0 <= s, t < n
- The graph may be disconnected; return -1 when t is unreachable from s.
- Parallel edges (multiple edges between the same pair) and self-loops may appear.
Examples
Input: (5, [[0,1,4],[0,2,1],[2,1,2],[1,3,1],[2,3,5]], 0, 3, True)
Expected Output: 4
Explanation: Directed graph. The path 0->2->1->3 costs 1+2+1=4, which beats 0->1->3 (4+1=5) and 0->2->3 (1+5=6). The two frontiers meet at node 1; best = dist_f[1]=3 plus dist_r[1]=1 gives 4.
Input: (4, [[0,1,1],[1,2,1],[2,3,1]], 0, 3, True)
Expected Output: 3
Explanation: A simple directed chain 0->1->2->3 of three unit edges. Shortest distance is 3.
Input: (3, [[0,1,2],[2,1,3]], 0, 2, True)
Expected Output: -1
Explanation: Directed graph where node 2 has only an outgoing edge to 1 and no path leads into 2 from 0. The reverse search from 2 cannot reach 0, so t is unreachable -> -1.
Input: (1, [], 0, 0, True)
Expected Output: 0
Explanation: Source equals target with a single node and no edges. The distance is 0 by definition.
Input: (4, [[0,1,10],[1,2,10],[0,3,1],[3,2,1]], 0, 2, False)
Expected Output: 2
Explanation: Undirected graph. The detour 0-3-2 costs 1+1=2, far cheaper than 0-1-2 (10+10=20). Edges are usable in both directions.
Input: (6, [[0,1,7],[0,2,9],[0,5,14],[1,2,10],[1,3,15],[2,3,11],[2,5,2],[3,4,6],[5,4,9]], 0, 4, False)
Expected Output: 20
Explanation: Classic undirected Dijkstra example. Shortest 0->4 is 0-2-5-4 = 9+2+9 = 20 (better than 0-2-3-4 = 9+11+6 = 26).
Input: (2, [[0,1,5]], 0, 1, False)
Expected Output: 5
Explanation: A single undirected edge of weight 5 between source and target.
Input: (3, [[0,1,1],[0,1,4],[1,2,2]], 0, 2, True)
Expected Output: 3
Explanation: Parallel edges 0->1 of weights 1 and 4; Dijkstra picks the cheaper (1), then 1->2 (2), total 3. Confirms duplicate edges are handled.
Hints
- Run two Dijkstra searches at once: a forward one from s on the original graph and a reverse one from t on the edge-reversed graph. Keep separate distance arrays dist_f and dist_r and a min-heap for each.
- Each time you relax an edge into a node v that the OTHER search has already reached, update best = min(best, dist_f[u] + w + dist_r[v]). Do not assume the answer is found the instant the frontiers first touch — that touching node is not always on the shortest path.
- Correct termination: stop when (top key of forward heap) + (top key of reverse heap) >= best. At that point no unexplored path can be shorter than the best meeting value already recorded. For unreachable targets one heap empties first; return -1.
- Handle s == t up front (answer 0), and for undirected graphs add each edge to both the forward and the reverse adjacency lists in both directions.