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
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.
/*
* 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)
- Why is the first visit the shortest?