DSA Graphs

Bus Routes

BFS on the bipartite stop–route graph — each layer represents one bus transfer.

Hard
Time O(N * R) Space O(N * R)
LeetCode
5 min read
graph bfs hashing

Problem#

Given routes[i] as the list of stops bus i cycles through, return the minimum number of buses you must take to travel from stop source to stop target. Return -1 if impossible.

Examples#

  • routes = [[1,2,7],[3,6,7]], source = 1, target = 62
  • routes = [[7,12],[4,5,15],[6],[15,19],[9,12,13]], source = 15, target = 12-1

Constraints#

  • 1 <= routes.length <= 500, 1 <= routes[i].length <= 10^5.

Approach#

Build stopToRoutes: for each stop, the set of routes serving it. BFS layers represent bus transfers, not stops: enqueue stops, but when expanding, look at every route serving the current stop, then enqueue every unvisited stop on those routes. Mark routes as visited to avoid reprocessing.

Solution#

Bus Routes
class Solution {
public:
int numBusesToDestination(vector<vector<int>>& routes, int source, int target) {
if (source == target) return 0;
unordered_map<int, vector<int>> stopToRoutes;
for (int i = 0; i < (int)routes.size(); ++i)
for (int s : routes[i])
stopToRoutes[s].push_back(i);
unordered_set<int> visitedStops{source}, visitedRoutes;
queue<int> q;
q.push(source);
int buses = 0;
while (!q.empty()) {
++buses;
for (int sz = q.size(); sz > 0; --sz) {
int stop = q.front(); q.pop();
for (int r : stopToRoutes[stop]) {
if (visitedRoutes.count(r)) continue;
visitedRoutes.insert(r);
for (int ns : routes[r]) {
if (ns == target) return buses;
if (!visitedStops.count(ns)) {
visitedStops.insert(ns);
q.push(ns);
}
}
}
}
}
return -1;
}
};

Editorial#

The natural reduction is to a graph where layers count bus boardings. Marking routes as visited (not just stops) is critical for complexity — otherwise a popular bus could be re-scanned many times.

Complexity#

  • Time: O(sum of route sizes).
  • Space: O(sum of route sizes).

Concept revision#

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.