From da6fd9a73a395caee4f80de0ef4f15b7581231b7 Mon Sep 17 00:00:00 2001 From: Alexander Zhipa Date: Mon, 23 Sep 2024 10:40:25 -0400 Subject: [PATCH 1/4] feat: python impl for 0-1 BFS --- src/graph/01_bfs.md | 109 +++++++++++++++++++++++++++++--------------- 1 file changed, 71 insertions(+), 38 deletions(-) diff --git a/src/graph/01_bfs.md b/src/graph/01_bfs.md index 5d7aee6f4..5ded8c342 100644 --- a/src/graph/01_bfs.md +++ b/src/graph/01_bfs.md @@ -17,27 +17,44 @@ In this article we demonstrate how we can use BFS to solve the SSSP (single-sour We can develop the algorithm by closely studying Dijkstra's algorithm and thinking about the consequences that our special graph implies. The general form of Dijkstra's algorithm is (here a `set` is used for the priority queue): -```cpp -d.assign(n, INF); -d[s] = 0; -set> q; -q.insert({0, s}); -while (!q.empty()) { - int v = q.begin()->second; - q.erase(q.begin()); - - for (auto edge : adj[v]) { - int u = edge.first; - int w = edge.second; - - if (d[v] + w < d[u]) { - q.erase({d[u], u}); - d[u] = d[v] + w; - q.insert({d[u], u}); +=== "C++" + ```cpp + d.assign(n, INF); + d[s] = 0; + set> q; + q.insert({0, s}); + while (!q.empty()) { + int v = q.begin()->second; + q.erase(q.begin()); + + for (auto edge : adj[v]) { + int u = edge.first; + int w = edge.second; + + if (d[v] + w < d[u]) { + q.erase({d[u], u}); + d[u] = d[v] + w; + q.insert({d[u], u}); + } } } -} -``` + ``` +=== "Python" + ```py + from heapq import heappop, heappush + + + d = [float("inf")] * n + d[s] = 0 + q = [(0, s)] + while q: + dv, v = heappop(q) + if dv == d[v]: + for u, w in adj[v]: + if d[v] + w < d[u]: + d[u] = d[v] + w + heappush(q, (d[u], u)) + ``` 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. Especially, we know that $d[v] \le d[u] \le d[v] + 1$ for each $u \in Q$. @@ -53,27 +70,43 @@ This structure is so simple, that we don't need an actual priority queue, i.e. u 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$. This way the queue still remains sorted at all time. -```cpp -vector d(n, INF); -d[s] = 0; -deque q; -q.push_front(s); -while (!q.empty()) { - int v = q.front(); - q.pop_front(); - for (auto edge : adj[v]) { - int u = edge.first; - int w = edge.second; - if (d[v] + w < d[u]) { - d[u] = d[v] + w; - if (w == 1) - q.push_back(u); - else - q.push_front(u); +=== "C++" + ```cpp + vector d(n, INF); + d[s] = 0; + deque q; + q.push_front(s); + while (!q.empty()) { + int v = q.front(); + q.pop_front(); + for (auto edge : adj[v]) { + int u = edge.first; + int w = edge.second; + if (d[v] + w < d[u]) { + d[u] = d[v] + w; + if (w == 1) + q.push_back(u); + else + q.push_front(u); + } } } -} -``` + ``` +=== "Python" + ```py + d = [float("inf")] * n + d[s] = 0 + q = deque([s]) + while q: + v = q.popleft() + for u, w in adj[v]: + if d[v] + w < d[u]: + d[u] = d[v] + w + if w == 1: + q.append(u) + else: + q.appendleft(u) + ``` ## Dial's algorithm From 6e98192a19d0ad436e3303c150060dc322a4b9cb Mon Sep 17 00:00:00 2001 From: Michael Hayter Date: Mon, 25 Aug 2025 18:33:56 -0700 Subject: [PATCH 2/4] Update src/graph/01_bfs.md Co-authored-by: Oleksandr Kulkov --- src/graph/01_bfs.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/graph/01_bfs.md b/src/graph/01_bfs.md index 5ded8c342..632941dd5 100644 --- a/src/graph/01_bfs.md +++ b/src/graph/01_bfs.md @@ -74,14 +74,11 @@ This way the queue still remains sorted at all time. ```cpp vector d(n, INF); d[s] = 0; - deque q; - q.push_front(s); - while (!q.empty()) { + deque q = {s}; + while (!empty(q)) { int v = q.front(); q.pop_front(); - for (auto edge : adj[v]) { - int u = edge.first; - int w = edge.second; + for (auto [u, w] : adj[v]) { if (d[v] + w < d[u]) { d[u] = d[v] + w; if (w == 1) From 96d4b88fed63b9873c8eb4e4eb2c29fa7e4a74aa Mon Sep 17 00:00:00 2001 From: Michael Hayter Date: Mon, 25 Aug 2025 18:34:29 -0700 Subject: [PATCH 3/4] Update src/graph/01_bfs.md Co-authored-by: Oleksandr Kulkov --- src/graph/01_bfs.md | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/graph/01_bfs.md b/src/graph/01_bfs.md index 632941dd5..1ccabcf3c 100644 --- a/src/graph/01_bfs.md +++ b/src/graph/01_bfs.md @@ -21,20 +21,16 @@ The general form of Dijkstra's algorithm is (here a `set` is used for the priori ```cpp d.assign(n, INF); d[s] = 0; - set> q; - q.insert({0, s}); - while (!q.empty()) { - int v = q.begin()->second; - q.erase(q.begin()); - - for (auto edge : adj[v]) { - int u = edge.first; - int w = edge.second; - - if (d[v] + w < d[u]) { - q.erase({d[u], u}); - d[u] = d[v] + w; - q.insert({d[u], u}); + priority_queue> q = {{0, s}}; + while (!empty(q)) { + int [dv, v] = q.top(); + q.pop(); + if (-dv == d[v]) { + for (auto [u, w] : adj[v]) { + if (d[v] + w < d[u]) { + d[u] = d[v] + w; + q.insert({-d[u], u}); + } } } } From 36a53da92901ea7d89d772036c294cc9a86b5f8b Mon Sep 17 00:00:00 2001 From: Michael Hayter Date: Mon, 25 Aug 2025 19:36:05 -0700 Subject: [PATCH 4/4] C++ code compiles + extra parallel to python --- src/graph/01_bfs.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/graph/01_bfs.md b/src/graph/01_bfs.md index 1ccabcf3c..d6f38e531 100644 --- a/src/graph/01_bfs.md +++ b/src/graph/01_bfs.md @@ -15,21 +15,23 @@ In this article we demonstrate how we can use BFS to solve the SSSP (single-sour ## Algorithm We can develop the algorithm by closely studying Dijkstra's algorithm and thinking about the consequences that our special graph implies. -The general form of Dijkstra's algorithm is (here a `set` is used for the priority queue): +The general form of Dijkstra's algorithm is: === "C++" ```cpp + int n = adj.size(); d.assign(n, INF); d[s] = 0; - priority_queue> q = {{0, s}}; - while (!empty(q)) { - int [dv, v] = q.top(); + priority_queue,vector>, greater> > q; + q.push({0,s}); + while (!q.empty()) { + auto [dv, v] = q.top(); q.pop(); - if (-dv == d[v]) { + if (dv == d[v]) { for (auto [u, w] : adj[v]) { if (d[v] + w < d[u]) { d[u] = d[v] + w; - q.insert({-d[u], u}); + q.push({d[u], u}); } } }