815. Bus Routes

139 阅读1分钟

image.png

方法:建图,bfs

  • 建图,key为stop,value为哪些路线(index)包含这个stop。

  • 起始时将「起点车站」所能进入的「路线」进行入队,每次从队列中取出「路线」时,查看该路线是否包含「终点车站」:

  • 包含「终点车站」:返回进入该线路所花费的距离

  • 不包含「终点车站」:遍历该路线所包含的车站,将由这些车站所能进入的路线,进行入队

  • 一些细节:由于是求最短路,同一路线重复入队是没有意义的,因此将新路线入队前需要先判断是否曾经入队。

class Solution {
    public int numBusesToDestination(int[][] routes, int source, int target) {
        if (source == target) {
            return 0;
        }
        // 建图,stop - routes that include this stop
        Map<Integer, List<Integer>> graph = new HashMap<>();
        for (int i = 0; i < routes.length; i++) {
            for (int stop : routes[i]) {
                List<Integer> list = graph.getOrDefault(stop, new ArrayList<>());
                list.add(i); // 存route的index
                graph.put(stop, list);
            }
        }

        // 如果起点或者终点不存在
        if (!graph.containsKey(source) || !graph.containsKey(target)) {
            return -1;
        }

        // queue里存route
        Queue<Integer> queue = new LinkedList<>();

        // 已经访问过的route
        Set<Integer> visitedRoute = new HashSet<>();
        
        // 包含起点的route
        for (int route : graph.get(source)) {
            queue.add(route);
            visitedRoute.add(route);
        }

        // 经过了几种route
        int count = 0;
        while (!queue.isEmpty()) {
            count++;
            int size = queue.size();

            for (int i = 0; i < size; i++) {
                int curRoute = queue.poll();

                // 遍历当前route可以覆盖的stop
                for (int stop : routes[curRoute]) {
                    // 可以到达target
                    if (stop == target) {
                        return count;
                    }
                    // 当前route覆盖不了target,遍历从当前stop出发的route
                    for (int nextRoute : graph.get(stop)) {
                        if (!visitedRoute.contains(nextRoute)) {
                            queue.offer(nextRoute);
                            visitedRoute.add(nextRoute);
                        }
                    }
                }
            }
        }

        return -1;
    }
}