You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/graph/01_bfs.md
+69-39Lines changed: 69 additions & 39 deletions
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@ tags:
7
7
8
8
It is well-known, that you can find the shortest paths between a single source and all other vertices in $O(|E|)$ using [Breadth First Search](breadth-first-search.md) in an **unweighted graph**, i.e. the distance is the minimal number of edges that you need to traverse from the source to another vertex.
9
9
We can interpret such a graph also as a weighted graph, where every edge has the weight $1$.
10
-
If not all edges in graph have the same weight, that we need a more general algorithm, like [Dijkstra](dijkstra.md) which runs in $O(|V|^2 + |E|)$ or $O(|E| \log |V|)$ time.
10
+
If not all edges in graph have the same weight, then we need a more general algorithm, like [Dijkstra](dijkstra.md) which runs in $O(|V|^2 + |E|)$ or $O(|E| \log |V|)$ time.
11
11
12
12
However if the weights are more constrained, we can often do better.
13
13
In this article we demonstrate how we can use BFS to solve the SSSP (single-source shortest path) problem in $O(|E|)$, if the weight of each edge is either $0$ or $1$.
@@ -17,27 +17,41 @@ In this article we demonstrate how we can use BFS to solve the SSSP (single-sour
17
17
We can develop the algorithm by closely studying Dijkstra's algorithm and thinking about the consequences that our special graph implies.
18
18
The general form of Dijkstra's algorithm is (here a `set` is used for the priority queue):
19
19
20
-
```cpp
21
-
d.assign(n, INF);
22
-
d[s] = 0;
23
-
set<pair<int, int>> q;
24
-
q.insert({0, s});
25
-
while (!q.empty()) {
26
-
int v = q.begin()->second;
27
-
q.erase(q.begin());
28
-
29
-
for (auto edge : adj[v]) {
30
-
int u = edge.first;
31
-
int w = edge.second;
32
-
33
-
if (d[v] + w < d[u]) {
34
-
q.erase({d[u], u});
35
-
d[u] = d[v] + w;
36
-
q.insert({d[u], u});
20
+
=== "C++"
21
+
```cpp
22
+
d.assign(n, INF);
23
+
d[s] = 0;
24
+
set<pair<int, int>> q;
25
+
q.insert({0, s});
26
+
while (!q.empty()) {
27
+
int v = q.begin()->second;
28
+
q.erase(q.begin());
29
+
30
+
for (auto edge : adj[v]) {
31
+
int u = edge.first;
32
+
int w = edge.second;
33
+
34
+
if (d[v] + w < d[u]) {
35
+
q.erase({d[u], u});
36
+
d[u] = d[v] + w;
37
+
q.insert({d[u], u});
38
+
}
37
39
}
38
40
}
39
-
}
40
-
```
41
+
```
42
+
=== "Python"
43
+
```py
44
+
d = [float("inf")] * n
45
+
d[s] = 0
46
+
q = {(0, s)}
47
+
while q:
48
+
_, v = q.pop()
49
+
for u, w in adj[v]:
50
+
if d[v] + w < d[u]:
51
+
q.discard((d[u], u))
52
+
d[u] = d[v] + w
53
+
q.add((d[u], u))
54
+
```
41
55
42
56
We can notice that the difference between the distances between the source `s` and two other vertices in the queue differs by at most one.
43
57
Especially, we know that $d[v] \le d[u] \le d[v] + 1$ for each $u \in Q$.
@@ -53,27 +67,43 @@ This structure is so simple, that we don't need an actual priority queue, i.e. u
53
67
We can simply use a normal queue, and append new vertices at the beginning if the corresponding edge has weight $0$, i.e. if $d[u] = d[v]$, or at the end if the edge has weight $1$, i.e. if $d[u] = d[v] + 1$.
54
68
This way the queue still remains sorted at all time.
0 commit comments