Skip to content

Commit ce4aff3

Browse files
committed
update bridges
1 parent 73e5617 commit ce4aff3

File tree

3 files changed

+43
-48
lines changed

3 files changed

+43
-48
lines changed

library/graphs/bridges_cuts/bridge_tree.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111
//! @time O(n + m)
1212
//! @space O(n)
1313
template<class G>
14-
vector<vi> bridge_tree(const G& adj,
15-
const bridges<G>& br) {
16-
vector<vi> tree(br.num_ccs);
14+
vector<vi> bridge_tree(const G& adj, int num_ccs,
15+
const vi& br_id, const vi& is_br) {
16+
vector<vi> tree(num_ccs);
1717
rep(i, 0, sz(adj)) for (auto [u, e_id] : adj[i]) if (
18-
br.is_bridge[e_id]) tree[br.br_id[i]]
19-
.push_back(br.br_id[u]);
18+
is_br[e_id]) tree[br_id[i]]
19+
.push_back(br_id[u]);
2020
return tree;
2121
}

library/graphs/bridges_cuts/bridges.hpp

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,39 +9,36 @@
99
//! adj[u].emplace_back(v, i);
1010
//! adj[v].emplace_back(u, i);
1111
//! }
12-
//! auto [num_ccs, is_bridge, br_id] = bridges(adj, m);
12+
//! auto [num_ccs, is_br, br_id] = bridges(adj, m);
1313
//! vector<basic_string<array<int,2>>> adj1(n);
1414
//! auto [num_ccs1, is_bridge1, br_id1] = bridges(adj1,
1515
//! m);
1616
//! @endcode
17-
//! is_bridge[edge id] = 1 iff bridge edge
17+
//! is_br[edge id] = 1 iff bridge edge
1818
//! br_id[v] = id, 0<=id<num_ccs
1919
//! @time O(n + m)
2020
//! @space O(n + m)
21-
template<class G> struct bridges {
22-
int num_ccs = 0;
23-
vector<bool> is_bridge;
24-
vi br_id;
25-
bridges(const G& adj, int m):
26-
is_bridge(m), br_id(sz(adj), -1) {
27-
int n = sz(adj), timer = 1;
28-
vi tin(n), st;
29-
auto dfs = [&](auto&& self, int v, int p_id) -> int {
30-
int low = tin[v] = timer++, siz = sz(st);
31-
st.push_back(v);
32-
for (auto [u, e_id] : adj[v]) {
33-
if (e_id == p_id) continue;
21+
template<class G>
22+
tuple<int, vi, vi> bridges(const G& adj, int m) {
23+
int n = sz(adj), num_ccs = 0, timer = 0;
24+
vi br_id(n, -1), is_br(m), tin(n), st;
25+
auto dfs = [&](auto&& self, int v, int p_id) -> int {
26+
int low = tin[v] = ++timer, siz = sz(st);
27+
st.push_back(v);
28+
for (auto [u, e_id] : adj[v])
29+
if (e_id != p_id) {
30+
// TODO golf this
3431
if (!tin[u]) low = min(low, self(self, u, e_id));
3532
low = min(low, tin[u]);
3633
}
37-
if (tin[v] == low) {
38-
if (p_id != -1) is_bridge[p_id] = 1;
39-
rep(i, siz, sz(st)) br_id[st[i]] = num_ccs;
40-
st.resize(siz);
41-
num_ccs++;
42-
}
43-
return low;
44-
};
45-
rep(i, 0, n) if (!tin[i]) dfs(dfs, i, -1);
46-
}
47-
};
34+
if (tin[v] == low) {
35+
if (p_id != -1) is_br[p_id] = 1;
36+
rep(i, siz, sz(st)) br_id[st[i]] = num_ccs;
37+
st.resize(siz);
38+
num_ccs++;
39+
}
40+
return low;
41+
};
42+
rep(i, 0, n) if (!tin[i]) dfs(dfs, i, -1);
43+
return {num_ccs, br_id, is_br};
44+
}

tests/library_checker_aizu_tests/graphs/two_edge_components.test.cpp

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,54 +16,52 @@ int main() {
1616
adj[v].emplace_back(u, i);
1717
edges[i] = {u, v};
1818
}
19-
bridges br(adj, m);
20-
vector<vector<int>> bt = bridge_tree(adj, br);
21-
assert(find(begin(br.br_id), end(br.br_id), -1) ==
22-
end(br.br_id));
19+
auto [num_ccs, br_id, is_br] = bridges(adj, m);
20+
vector<vector<int>> bt =
21+
bridge_tree(adj, num_ccs, br_id, is_br);
22+
assert(find(begin(br_id), end(br_id), -1) == end(br_id));
2323
// check correctness of bridge tree
2424
{
25-
assert(sz(bt) == br.num_ccs);
26-
for (int v = 0; v < br.num_ccs; v++)
25+
assert(sz(bt) == num_ccs);
26+
for (int v = 0; v < num_ccs; v++)
2727
for (auto to : bt[v])
2828
assert(to != v); // didn't add any non-bridge
2929
int sum_deg = accumulate(begin(bt), end(bt), 0,
3030
[](int sum, const auto& neighbors) -> int {
3131
return sum + sz(neighbors);
3232
});
33-
int cnt_bridges = accumulate(begin(br.is_bridge),
34-
end(br.is_bridge), 0);
33+
int cnt_bridges =
34+
accumulate(begin(is_br), end(is_br), 0);
3535
assert(sum_deg % 2 == 0 && sum_deg / 2 == cnt_bridges);
3636
}
3737
dsu_restorable dsu(n);
3838
int num_sets_dsu = n;
3939
for (int i = 0; i < m; i++) {
40-
if (!br.is_bridge[i]) {
40+
if (!is_br[i]) {
4141
auto [u, v] = edges[i];
4242
num_sets_dsu -= dsu.join(u, v);
4343
}
4444
}
4545
assert(num_sets_dsu == sz(bt));
4646
for (int i = 0; i < m; i++) {
47-
if (br.is_bridge[i]) {
47+
if (is_br[i]) {
4848
auto [u, v] = edges[i];
4949
bool same_set = dsu.same_set(u, v);
5050
assert(!same_set);
5151
}
5252
}
5353
for (int i = 0; i < n; i++) {
5454
int par_of_cc = dsu.find(i);
55-
assert(br.br_id[i] == br.br_id[par_of_cc]);
55+
assert(br_id[i] == br_id[par_of_cc]);
5656
}
5757
for (int i = 0; i < m; i++) {
5858
auto [u, v] = edges[i];
5959
// bridge if nodes are from different 2-edge CCs
60-
assert(
61-
br.is_bridge[i] == (br.br_id[u] != br.br_id[v]));
60+
assert(is_br[i] == (br_id[u] != br_id[v]));
6261
}
63-
vector<vector<int>> ccs(br.num_ccs);
64-
for (int i = 0; i < n; i++)
65-
ccs[br.br_id[i]].push_back(i);
66-
cout << br.num_ccs << '\n';
62+
vector<vector<int>> ccs(num_ccs);
63+
for (int i = 0; i < n; i++) ccs[br_id[i]].push_back(i);
64+
cout << num_ccs << '\n';
6765
for (const auto& curr_cc : ccs) {
6866
cout << sz(curr_cc) << " ";
6967
for (auto node : curr_cc) cout << node << " ";

0 commit comments

Comments
 (0)