From 115e2b203f6dbdc1f0707b59ccc2a46e24f54fb5 Mon Sep 17 00:00:00 2001 From: NaimSS Date: Sat, 4 May 2024 11:10:05 +0200 Subject: [PATCH 1/2] fix bug in bridge searching offline algorithm in case of duplicate edges --- src/graph/bridge-searching.md | 11 ++++-- test/test_bridge_searching_offline.cpp | 48 ++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 test/test_bridge_searching_offline.cpp diff --git a/src/graph/bridge-searching.md b/src/graph/bridge-searching.md index 2d6596878..50d3de034 100644 --- a/src/graph/bridge-searching.md +++ b/src/graph/bridge-searching.md @@ -40,7 +40,10 @@ The implementation needs to distinguish three cases: when we go down the edge in To implement this, we need a depth first search function which accepts the parent vertex of the current node. -```cpp +For the cases of multiple edges, we need to be careful when ignoring the edge from the parent. To solve this issue, we can add a flag `parent_skipped` which will ensure we only skip the parent once. + +```{.cpp file=bridge_searching_offline} +void IS_BRIDGE(int v,int to); // some function to process the found bridge int n; // number of nodes vector> adj; // adjacency list of graph @@ -51,8 +54,12 @@ int timer; void dfs(int v, int p = -1) { visited[v] = true; tin[v] = low[v] = timer++; + bool parent_skipped = false; for (int to : adj[v]) { - if (to == p) continue; + if (to == p && !parent_skipped) { + parent_skipped = true; + continue; + } if (visited[to]) { low[v] = min(low[v], tin[to]); } else { diff --git a/test/test_bridge_searching_offline.cpp b/test/test_bridge_searching_offline.cpp new file mode 100644 index 000000000..269254c19 --- /dev/null +++ b/test/test_bridge_searching_offline.cpp @@ -0,0 +1,48 @@ +#include +#include +#include +using namespace std; + +#include "bridge_searching_offline.h" + +vector> bridges; +void IS_BRIDGE(int v,int to){ + bridges.push_back({v, to}); +} + +void normalize(vector> &v){ + for(auto &p : v){ + if(p.first > p.second)swap(p.first, p.second); + } + sort(v.begin(), v.end()); +} + +void test_suite( + int _n, + vector> _adj, + vector > expected_bridges){ + bridges.clear(); + n = _n; + adj = _adj; + find_bridges(); + normalize(&expected_bridges); + normalize(&bridges); + assert(bridges == expected_bridges); +} + +int main() { + { + int n = 5; + vector> adj(n); + adj[0].push_back(1), adj[1].push_back(0); + adj[0].push_back(1), adj[1].push_back(0); + + adj[2].push_back(3), adj[3].push_back(2); + adj[3].push_back(4), adj[4].push_back(3); + vector > expected_bridges; + expected_bridges.push_back({2,3}); + expected_bridges.push_back({3,4}); + // note that 0-1 is not a bridge due to duplicate edges! + test_suite(n, adj, expected_bridges); + } +} From cbcce391e0f2b08aed5598b4b93ebfd5b6b94b58 Mon Sep 17 00:00:00 2001 From: NaimSS Date: Sat, 4 May 2024 11:20:22 +0200 Subject: [PATCH 2/2] improve test cases --- test/test_bridge_searching_offline.cpp | 50 ++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/test/test_bridge_searching_offline.cpp b/test/test_bridge_searching_offline.cpp index 269254c19..8ca73fba0 100644 --- a/test/test_bridge_searching_offline.cpp +++ b/test/test_bridge_searching_offline.cpp @@ -25,24 +25,60 @@ void test_suite( n = _n; adj = _adj; find_bridges(); - normalize(&expected_bridges); - normalize(&bridges); + normalize(expected_bridges); + normalize(bridges); assert(bridges == expected_bridges); } int main() { + vector> adj; + auto add_edge = [&](int a,int b){ + adj[a].push_back(b); + adj[b].push_back(a); + }; { int n = 5; - vector> adj(n); - adj[0].push_back(1), adj[1].push_back(0); - adj[0].push_back(1), adj[1].push_back(0); + adj.resize(n); + add_edge(0, 1); + add_edge(0, 1); - adj[2].push_back(3), adj[3].push_back(2); - adj[3].push_back(4), adj[4].push_back(3); + add_edge(2, 3); + add_edge(3, 4); vector > expected_bridges; expected_bridges.push_back({2,3}); expected_bridges.push_back({3,4}); // note that 0-1 is not a bridge due to duplicate edges! test_suite(n, adj, expected_bridges); + adj.clear(); + } + { + int n = 7; + adj.resize(n); + add_edge(0, 1); + add_edge(1, 2); + add_edge(2, 3); + add_edge(3, 1); + add_edge(3, 4); + add_edge(0, 4); + add_edge(4, 5); + add_edge(1, 6); + vector > expected_bridges; + expected_bridges.push_back({4, 5}); + expected_bridges.push_back({1, 6}); + test_suite(n, adj, expected_bridges); + adj.clear(); + } + { + int n = 4; + adj.resize(n); + add_edge(0, 1); + add_edge(0, 1); + add_edge(1, 2); + add_edge(2, 3); + add_edge(2, 3); + vector > expected_bridges; + expected_bridges.push_back({1, 2}); + test_suite(n, adj, expected_bridges); + adj.clear(); } }