class Solution {
class Node{
int stop;
int level;
public Node(int stop, int level){
this.stop = stop;
this.level = level;
}
}
public int numBusesToDestination(int[][] routes, int source, int target) {
if(source == target) return 0;
Queue<Node> q = new LinkedList<>();
Set<Integer> visited = new HashSet<>();
Map<Integer, List<Integer>> stopToRoutes = new HashMap<>();
for(int i = 0; i < routes.length; i++){
for(int j = 0; j < routes[i].length; j++){
// create adjList between each stop and the routes that stop is in
List<Integer> listOfRoutes = stopToRoutes.getOrDefault(routes[i][j], new ArrayList());
stopToRoutes.put(routes[i][j], listOfRoutes);
listOfRoutes.add(i);
}
}
// add the starting stop and level as 0
q.add(new Node(source, 0));
while(!q.isEmpty()){
Node curr = q.poll();
int stop = curr.stop;
// if this is the destination then return the current level
if(stop == target){
return curr.level;
}
// add the stop to the visited set so that we don't visit this stop again
visited.add(stop);
// get all routes that can be accessed from this stop
for(Integer route : stopToRoutes.get(stop)){
// get all possibleStop on this route
for(int possibleStop : routes[route]){
// if this stop hasn't been visited, add it to the q to visit it
if(!visited.contains(possibleStop)){
q.add(new Node(possibleStop, curr.level + 1));
}
}
// getting tle without this
// once a route has been explored, we've seen all stops in this route, so we can set it to empty
routes[route] = new int[]{};
}
}
return -1;
}
}