This repository has been archived on 2022-06-22. You can view files and clone it, but cannot push or open issues or pull requests.
usaco-guide/content/4_Gold/BFS.mdx
2020-07-19 02:50:00 -04:00

216 lines
6.9 KiB
Text

---
id: bfs
title: "Breadth First Search (BFS)"
author: Benjamin Qi, Michael Cao
prerequisites:
- dfs
description: "Traversing a graph in a way such that vertices closer to the starting vertex are processed first."
frequency: 2
---
import { Problem } from "../models";
export const metadata = {
problems: {
sample: [
new Problem("CSES", "Message Route", "1667", "Easy", false, ["BFS"]),
],
general: [
new Problem("CSES", "Monsters", "1194", "Easy", false, ["BFS"]),
new Problem("CSA", "BFS-DFS", "bfs-dfs", "Normal", false, ["BFS", "DFS"]),
new Problem("Gold", "Lasers", "671", "Normal", false, ["BFS"]),
new Problem("Gold", "Dream", "575", "Hard", false, ["BFS"]),
new Problem("Gold", "A Pie for a Pie", "765", "Very Hard", false, [], ""),
],
example: [
new Problem("Gold", "Cow Navigation", "695", "Normal", false, ["BFS"]),
]
}
};
<Problems problems={metadata.problems.sample} />
## Resources
<Resources>
<Resource source="CSA" title="Breadth First Search" url="breadth_first_search" starred>interactive</Resource>
<Resource source="CPH" title="12.2 - Breadth-First Search"></Resource>
<Resource source="PAPS" title="12.1 - Breadth-First Search"></Resource>
<Resource source="KA" title="Breadth First Search and Its Uses" url="https://www.khanacademy.org/computing/computer-science/algorithms/breadth-first-search/a/breadth-first-search-and-its-uses"></Resource>
<Resource source="cp-algo" title="Breadth First Search" url="graph/breadth-first-search.html"></Resource>
<Resource source="cp-algo" title="0/1 BFS" url="graph/01_bfs.html"></Resource>
<Resource source="IUSACO" title="10.4 - Graph Traversal Algorithms"></Resource>
</Resources>
## Implementation
<LanguageSection>
<CPPSection>
From the CSA article:
```cpp
#include <algorithm>
#include <fstream>
#include <iostream>
#include <queue>
using namespace std;
const int MAX_N = 100005;
vector<int> graph[MAX_N];
int dist[MAX_N];
bool visited[MAX_N];
void bfs(int startNode) {
dist[startNode] = 0;
queue<int> bfsQueue;
bfsQueue.push(startNode);
visited[startNode] = true;
while (!bfsQueue.empty()) {
int currentNode = bfsQueue.front();
bfsQueue.pop();
for (auto neighbour: graph[currentNode]) {
if (!visited[neighbour]) {
visited[neighbour] = true;
dist[neighbour] = dist[currentNode] + 1;
bfsQueue.push(neighbour);
}
}
}
}
int main() {
int N, M, v, x, y;
cin >> N >> M >> v;
for (int i = 1; i <= M; i += 1) {
cin >> x >> y;
graph[x].push_back(y);
}
for (int i = 1; i <= N; i += 1) {
dist[i] = -1;
}
bfs(v);
for (int i = 1; i <= N; i += 1) {
cout << dist[i] << " ";
}
return 0;
}
```
</CPPSection>
<JavaSection>
Implementation of the CSAcademy article's problem in Java:
```java
import java.util.*;
import java.io.*;
class Main {
static ArrayList<Integer> edges[];
static int dist[];
static boolean visited[];
static void bfs(int startNode) {
Queue<Integer> q = new ArrayDeque<Integer>(); //You can choose any implementation of Queue (such as LinkedList), though I believe ArrayDeque is faster (?)
q.add(startNode);
visited[startNode] = true;
dist[startNode] = 0;
while(!q.isEmpty()) {
int currentNode = q.poll();
for(int adj : edges[currentNode]) {
if(!visited[adj]) {
visited[adj] = true;
dist[adj] = dist[currentNode]+1;
q.add(adj);
}
}
}
}
public static void main (String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //Read about fast Java input in "Intro - Fast I/O"
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
int start = Integer.parseInt(st.nextToken());
start--;
edges = new ArrayList[N];
dist = new int[N];
visited = new boolean[N];
for(int i = 0; i < N; i++) {
edges[i] = new ArrayList<Integer>();
dist[i] = -1;
}
for(int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
a--; b--;
edges[a].add(b);
}
bfs(start);
PrintWriter pw = new PrintWriter(System.out);
for(int i : dist) pw.print(i + " ");
pw.println();
pw.close();
}
}
```
</JavaSection>
</LanguageSection>
## Example: Cow Navigation
In the gold division, the problem statement will never directly be, "Given an unweighted graph, find the shortest path between node $u$ and $v$." Instead, the difficulty in many BFS problems are modifying the problem into a graph on which we can run BFS and get the answer.
<Problems problems={metadata.problems.example} />
In this problem, Bessie stands on a grid and wants to go from the lower left corner to upper-right corner in as few moves as possible. An initial idea could be to model the grid as a graph, where adjacent cells are connected by edges, and run a BFS to find the shortest path.
However, two additional constriants play a role in this problem: Bessie must be able to reach the destination regardless of which direction she starts in, and she can only move in the direction she is facing.
Let's imagine now that there are two cows standing on the cell $(1, 1)$, and both of them move the same way on each operation. Since $N \leq 20$, we can modify the original graph to support this new problem. Let's create a new graph $G'$ as follows:
For each pair of cells in the grid, $(x, y)$ and $x_2, y_2$, add 16 <!-- wow that's a lot --> nodes in the graph storing six parameters each, {$x$ coordinate of cow $a$, $y$ coordinate of cow a, $x$ coordinate of cow $b$, $y$ coordinate of cow $b$, direction of cow $a$, direction of cow $b$} for all $4 ^ 2$ directions each cow could be facing.
Given this new graph, we add edges between two "states" which are reachable from each other. For example, if we apply the "turn left" operation, we add an edge to the state where both cows directions turn left.
On this new graph, we can directly run a BFS, and retrieve the answer at ${N, N, N, N, x, y}$ where $x$ and $y$ represent directions.
<Warning>
Don't forget that once Bessie reaches the goal, she will ignore further commands. In the modified problem, if one of the two cows is at the goal, stop applying commands to her.
</Warning>
(Ben - equivalent to existing editorial)
<!-- You can change it, but keep the section on making modifications to graphs before. Maybe replace with a problem w/o a good editorial? -->
### Implementation
<!-- I really don't want to write Cow Navigation. Anyone have code? -->
<IncompleteSection />
## Problems
<Problems problems={metadata.problems.general} />