Shortest Paths with Unweighted Edges
Authors: Benjamin Qi, Andi Qu, Neo Wang
Contributor: Qi Wang
Introduces how BFS can be used to find shortest paths in unweighted graphs.
Unweighted Shortest Path
Focus Problem – try your best to solve this problem before continuing!
Solution - Message Route
Time Complexity:
We can observe is that there are many possible shortest paths to output.
Fortunately, the problem states that we can print any valid solution. Notice
that like every other BFS problem, the distance of each node increases by
when we travel to the next level of unvisited nodes. However, the problem
requires that we add additional information - in this case, the path. When we
traverse from node to , we can set the parent of to . After the
BFS is complete, this allows us to backtrack through the parents which
ultimately leads us to our starting node. We know to terminate at node
because it's the starting node. If there is no path to our end node, then its
distance will remain at
INT_MAX
.
For the test input, we start with the following parent array.
Node | 1 | 2 | 3 | 4 | 5 |
Parent | 0 | 0 | 0 | 0 | 0 |
Distance | 0 | INT_MAX | INT_MAX | INT_MAX | INT_MAX |
After visiting children of node :
Node | 1 | 2 | 3 | 4 | 5 |
Parent | 0 | 1 | 1 | 1 | 0 |
Distance | 0 | 1 | 1 | 1 | INT_MAX |
After visiting node from node :
Node | 1 | 2 | 3 | 4 | 5 |
Parent | 0 | 1 | 1 | 1 | 4 |
Distance | 0 | 1 | 1 | 1 | 2 |
To determine the path, we can backtrack from node , in this case , pushing each value that we backtrack into a vector. The path we take is which corresponds to the vector . We break at node because it was the initial starting node. Finally, we reverse the vector and print out its length (in this case, ).
C++
#include <bits/stdc++.h>using namespace std;using vi = vector<int>;#define pb push_backint main() {int N, M;cin >> N >> M;vi dist(N + 1, INT_MAX), parent(N + 1);
Java
import java.io.*;import java.util.*;public class Solution {Code Snippet: Kattio (Click to expand)private static Map<Integer, LinkedList<Integer>> adj = new HashMap<>();public static void main(String[] args) {Kattio io = new Kattio();
Python
from collections import deque, defaultdictn, m = map(int, input().split())edges = []for _ in range(m):a, b = map(int, input().split())edges.append((a, b))graph = defaultdict(list)for a, b in edges:
Pro Tip
In the gold division, the problem statement will almost never directly be, "Given an unweighted graph, find the shortest path between node and ." Instead, the difficulty in many BFS problems are converting the problem into a graph on which we can run BFS and get the answer.
Extension - 0/1 BFS
Focus Problem – try your best to solve this problem before continuing!
A 0/1 BFS finds the shortest path in a graph where the weights on the edges can only be 0 or 1, and runs in using a deque. Read the resource below for an explanation of how the algorithm works.
Resources | ||||
---|---|---|---|---|
cp-algo | common applications |
Solution - Tracks in the Snow
Complexity:
We can use the following greedy strategy to find our answer:
- Run flood fill to find each connected component with the same tracks.
- Construct a graph where the nodes are the connected components and there are edges between adjacent connected components.
- The answer is the maximum distance from the node containing to another node. We can use BFS to find this distance.
For a detailed proof of why this works, see the official editorial.
Although this gives us an solution, there is a simpler solution using 0/1 BFS!
Consider the graph with an edge between each pair of adjacent cells with tracks, where the weight is 0 if the tracks are the same and 1 otherwise. The answer is simply the longest shortest-path from the top left cell. This is because going from one track to another same one is like not leaving a node (hence the cost is ), while going from one track to a different one is like traversing the edge between two nodes (hence the cost is ).
Since the weight of each edge is either 0 or 1 and we want the shortest paths from the top left cell to each other cell, we can apply 0/1 BFS. The time complexity of this solution is .
C++
#include <bits/stdc++.h>using namespace std;int dx[4]{1, -1, 0, 0}, dy[4]{0, 0, 1, -1};int n, m, depth[4000][4000], ans = 1;string snow[4000];bool inside(int x, int y) {return (x > -1 && x < n && y > -1 && y < m && snow[x][y] != '.');
Java
import java.io.*;import java.util.*;public class tracks {static final int[] dx = {0, 0, -1, 1};static final int[] dy = {-1, 1, 0, 0};static int N = 1, H, W;static int[][] grid, count;public static void main(String[] args) {FastIO io = new FastIO();
Warning!
Due to oj.uz's grading constraints for Java, this solution will TLE on the judge.
Problems
Status | Source | Problem Name | Difficulty | Tags | |
---|---|---|---|---|---|
CSES | Easy | Show TagsBFS | |||
Old Silver | Easy | Show TagsBFS | |||
CSES | Easy | Show TagsBFS | |||
Silver | Easy | Show TagsBFS | |||
CSES | Normal | Show TagsCycle | |||
CSA | Normal | Show TagsBFS, DFS | |||
Gold | Normal | Show TagsBFS | |||
AC | Normal | Show TagsBFS | |||
Gold | Normal | Show TagsBFS | |||
AC | Normal | Show TagsBFS | |||
IOI | Normal | Show TagsBFS, Binary Search | |||
CSES | Normal | Show TagsBFS | |||
IOI | Normal | Show TagsBFS | |||
Gold | Hard | Show TagsBFS | |||
Gold | Hard | Show TagsBFS |
Module Progress:
Join the USACO Forum!
Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!