Розбір
Breadth-First Search (or BFS) is a modification of the classic Breadth-First Search (BFS) algorithm, used for finding shortest paths in graphs. The key difference of this algorithm is that the edge weights in the graph can only be or , allowing for a significant optimization in search efficiency.
Problem Statement. Imagine we have a weighted graph where the edge weights are either or . For example, such a graph can represent a city where certain roads are free (weight ), while others have a toll (weight ). Our goal is to find the shortest path from one vertex to another, taking these weights into account.
Limitations of the Standard Breadth-First Search Algorithm. The classic BFS algorithm has a complexity of and is used to find shortest paths in unweighted graphs, but it only works effectively when all edges have the same weight. If edge weights vary, this approach becomes inefficient. Typically, Dijkstra's algorithm is used for weighted graphs, with a complexity of or . However, for graphs with edge weights of only and , there is a faster approach — BFS.
0-1 BFS Algorithm
In BFS, we use a double-ended queue (deque). The idea is as follows:
1. We start from the initial vertex and add it to the deque with an initial distance of .
2. When processing each vertex (which is dequeued from the front), we examine its neighbors :
If the edge has a weight of , the neighboring vertex is added to the front of the deque with the current distance .
If the edge has a weight of , the neighboring vertex is added to the back of the deque with an increased distance of one .
This ensures an efficient order of vertex processing: vertices reachable through edges with smaller weights are processed earlier.
Thus, the use of a double-ended queue guarantees that we always have access to the vertex with the minimum distance at the front of the deque, and the algorithm’s complexity remains .
Edge relaxation in BFS is similar to the classical relaxation in Dijkstra’s algorithm but differs in that it uses a deque instead of a priority queue to order vertices based on edge weights.
Let's consider the following example. Initialize the array of shortest distances and the queue :
Examine the edges originating from vertex and relax the edges and . Vertex will be added to the front of the queue, while vertex will be added to the back of the queue.
However, the value is not final. Traverse edge and set , making the queue . Then, examine edge , and the value is updated to . Thus, took on two different values as a result of relaxation (first , then ).
Example
The graph given in the example looks as follows:
The length of the shortest path from vertex to vertex is , and the shortest path is as follows: .
Algorithm realization
Declare the constant infinity.
#define INF 0x3F3F3F3F
Declare the array of shortest distances and the adjacency list of the graph .
vector<int> dist; vector<vector<pair<int, int>>> g;
The bfs function implements breadth-first search from the vertex .
void bfs(int start) {
Initialize the array of shortest distances .
dist = vector<int>(n + 1, INF); dist[start] = 0;
Declare a queue and enqueue the starting vertex .
deque<int> q; q.push_back(start);
Continue the breadth-first search algorithm while the queue is not empty.
while (!q.empty()) {
Extract the vertex from the front of the queue.
int v = q.front(); q.pop_front();
Iterate through the edges outgoing from vertex .
for (auto edge : g[v]) { int to = edge.first; int w = edge.second;
The current edge has a weight . Perform its relaxation.
if (dist[to] > dist[v] + w) {
If the edge is relaxed, recalculate the shortest distance .
dist[to] = dist[v] + w;
Depending on the weight of the edge , add vertex to the end or the front of the queue.
if (w == 1) q.push_back(to); else q.push_front(to); } } } }
The main part of the program. Read the input data.
scanf("%d %d %d %d", &n, &m, &s, &d); g.resize(n + 1);
Read the graph.
for (i = 0; i < m; i++) { scanf("%d %d %d", &a, &b, &w); g[a].push_back({ b, w }); g[b].push_back({ a, w }); }
Start the breadth-first search from the starting vertex .
bfs(s);
Print the shortest distance to vertex .
printf("%d\n", dist[d]);