Shortest Path in an Unweighted Graph (BFS)

Problem

The first line has n and m: nodes 0 to n-1 and m undirected edges. The next m lines have one edge each (a b). The last line has two nodes: start and target. Print the smallest number of edges on a path from start to target, or -1 if there is no path.

Constraints

  • 1 <= n <= 10^5
  • 0 <= m <= 2 * 10^5

Examples

Input

5 4
0 1
1 2
2 3
0 4
0 3

Output

3

Solutions

Best approachTime O(n + m)Space O(n + m)

BFS explores a graph level by level, so the first time it reaches a node is along a path with the fewest edges. This only works when all edges have the same cost; for different weights use Dijkstra.

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Shortest path.
 * Input   : n and m, m edges, then start and target.
 * Output  : The distance or -1.
 * Approach: BFS.
 * Time    : O(n + m)
 * Space   : O(n + m)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
    // This method solves the task. It receives the input and returns the answer.
    static int solve(String[] lines) {
        String[] header = lines[0].split(" ");
        int n = Integer.parseInt(header[0]);
        int m = Integer.parseInt(header[1]);

        // Step 1: Build the adjacency lists. The graph is undirected, so every edge is added in both directions.
        java.util.List<java.util.List<Integer>> neighbours = new java.util.ArrayList<>();
        for (int i = 0; i < n; i++) {
            neighbours.add(new java.util.ArrayList<>());
        }
        for (int i = 1; i <= m; i++) {
            String[] edge = lines[i].split(" ");
            int x = Integer.parseInt(edge[0]);
            int y = Integer.parseInt(edge[1]);
            neighbours.get(x).add(y);
            neighbours.get(y).add(x);
        }
        String[] query = lines[m + 1].split(" ");
        int start = Integer.parseInt(query[0]);
        int target = Integer.parseInt(query[1]);

        // Step 2: distance[v] = the number of edges from start to v. -1 means "not reached yet".
        int[] distance = new int[n];
        java.util.Arrays.fill(distance, -1);
        distance[start] = 0;
        java.util.ArrayDeque<Integer> queue = new java.util.ArrayDeque<>();
        queue.add(start);

        // Step 3: BFS visits the nodes in order of their distance. The first time we reach a node is its shortest distance.
        while (!queue.isEmpty()) {
            int node = queue.poll();
            for (int next : neighbours.get(node)) {
                if (distance[next] == -1) {
                    distance[next] = distance[node] + 1;
                    queue.add(next);
                }
            }
        }
        return distance[target];
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        java.util.List<String> all = new java.util.ArrayList<>();
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();
            if (!line.isEmpty()) {
                all.add(line);
            }
        }
        String[] lines = all.toArray(new String[0]);
        System.out.println(solve(lines));
    }
}
Hints (1)
  1. Why is the first visit the shortest?