Skip to content

Commit d617a7a

Browse files
committed
convert this now
1 parent 3b6e828 commit d617a7a

File tree

3 files changed

+51
-54
lines changed

3 files changed

+51
-54
lines changed

library/graphs/bridges_cuts/block_vertex_tree.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@
1919
//! @time O(n + m)
2020
//! @time O(n)
2121
template<class G>
22-
vector<vi> block_vertex_tree(const G& adj,
23-
const cuts<G>& cc) {
22+
vector<vi> block_vertex_tree(const G& adj, int num_bccs,
23+
const vi& bcc_id) {
2424
int n = sz(adj);
25-
vector<vi> bvt(n + cc.num_bccs);
26-
vector<bool> vis(cc.num_bccs);
25+
vector<vi> bvt(n + num_bccs);
26+
vector<bool> vis(num_bccs);
2727
rep(i, 0, n) {
2828
for (auto [_, e_id] : adj[i]) {
29-
int bccid = cc.bcc_id[e_id];
29+
int bccid = bcc_id[e_id];
3030
if (!vis[bccid]) {
3131
vis[bccid] = 1;
3232
bvt[i].push_back(bccid + n);

library/graphs/bridges_cuts/cuts.hpp

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,39 +18,35 @@
1818
//! bcc_id[edge id] = id, 0<=id<num_bccs
1919
//! @time O(n + m)
2020
//! @space O(n + m)
21-
template<class G> struct cuts {
22-
int num_bccs = 0;
23-
vector<bool> is_cut;
24-
vi bcc_id;
25-
cuts(const G& adj, int m):
26-
is_cut(sz(adj)), bcc_id(m, -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++, deg = 0;
31-
for (auto [u, e_id] : adj[v]) {
32-
assert(v != u);
33-
if (e_id == p_id) continue;
34-
if (!tin[u]) {
35-
int siz = sz(st);
36-
st.push_back(e_id);
37-
int low_ch = self(self, u, e_id);
38-
if (low_ch >= tin[v]) {
39-
is_cut[v] = 1;
40-
rep(i, siz, sz(st)) bcc_id[st[i]] = num_bccs;
41-
st.resize(siz);
42-
num_bccs++;
43-
}
44-
low = min(low, low_ch);
45-
deg++;
46-
} else if (tin[u] < tin[v]) {
47-
st.push_back(e_id);
48-
low = min(low, tin[u]);
21+
template<class G>
22+
tuple<int, vi, vi> cuts(const G& adj, int m) {
23+
int n = sz(adj), num_bccs = 0, timer = 0;
24+
vi bcc_id(m, -1), is_cut(n), tin(n), st;
25+
auto dfs = [&](auto&& self, int v, int p_id) -> int {
26+
int low = tin[v] = ++timer, deg = 0;
27+
for (auto [u, e_id] : adj[v]) {
28+
assert(v != u);
29+
if (e_id == p_id) continue;
30+
if (!tin[u]) {
31+
int siz = sz(st);
32+
st.push_back(e_id);
33+
int low_ch = self(self, u, e_id);
34+
if (low_ch >= tin[v]) {
35+
is_cut[v] = 1;
36+
rep(i, siz, sz(st)) bcc_id[st[i]] = num_bccs;
37+
st.resize(siz);
38+
num_bccs++;
4939
}
40+
low = min(low, low_ch);
41+
deg++;
42+
} else if (tin[u] < tin[v]) {
43+
st.push_back(e_id);
44+
low = min(low, tin[u]);
5045
}
51-
if (p_id == -1) is_cut[v] = (deg > 1);
52-
return low;
53-
};
54-
rep(i, 0, n) if (!tin[i]) dfs(dfs, i, -1);
55-
}
56-
};
46+
}
47+
if (p_id == -1) is_cut[v] = (deg > 1);
48+
return low;
49+
};
50+
rep(i, 0, n) if (!tin[i]) dfs(dfs, i, -1);
51+
return {num_bccs, bcc_id, is_cut};
52+
}

tests/library_checker_aizu_tests/graphs/biconnected_components.test.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,34 +15,35 @@ int main() {
1515
adj[v].emplace_back(u, i);
1616
edges[i] = make_pair(u, v);
1717
}
18-
cuts cc(adj, m);
19-
vector<vector<int>> bvt = block_vertex_tree(adj, cc);
20-
assert(find(begin(cc.bcc_id), end(cc.bcc_id), -1) ==
21-
end(cc.bcc_id));
18+
auto [num_bccs, bcc_id, is_cut] = cuts(adj, m);
19+
vector<vector<int>> bvt =
20+
block_vertex_tree(adj, num_bccs, bcc_id);
21+
assert(
22+
find(begin(bcc_id), end(bcc_id), -1) == end(bcc_id));
2223
for (int i = 0; i < n; i++) {
2324
// cut node if there exists a pair of adjacent edges
2425
// belonging to different BCCs
25-
bool is_cut = 0;
26+
bool curr_is_cut = 0;
2627
for (int j = 0; j < sz(adj[i]); j++)
27-
if (cc.bcc_id[adj[i][0].second] !=
28-
cc.bcc_id[adj[i][j].second])
29-
is_cut = 1;
30-
assert(is_cut == cc.is_cut[i]);
28+
if (bcc_id[adj[i][0].second] !=
29+
bcc_id[adj[i][j].second])
30+
curr_is_cut = 1;
31+
assert(curr_is_cut == is_cut[i]);
3132
}
3233
// check correctness of block vertex tree
3334
for (int i = 0; i < n; i++) {
3435
assert(sz(adj[i]) >=
3536
sz(bvt[i])); // in particular, if empty(adj[i]), then
3637
// empty(bct[i])
37-
assert(cc.is_cut[i] ==
38+
assert(is_cut[i] ==
3839
(sz(bvt[i]) >
3940
1)); // is cut means non-leaf in block vertex tree
4041
}
4142
{
42-
vector<set<int>> bcc_to_nodes(cc.num_bccs),
43+
vector<set<int>> bcc_to_nodes(num_bccs),
4344
node_to_bccs(n);
4445
for (int i = 0; i < m; i++) {
45-
int bccid = cc.bcc_id[i];
46+
int bccid = bcc_id[i];
4647
for (auto node : {edges[i].first, edges[i].second}) {
4748
bcc_to_nodes[bccid].insert(node);
4849
node_to_bccs[node].insert(bccid);
@@ -56,7 +57,7 @@ int main() {
5657
assert(node_to_bccs[u].contains(bccid));
5758
}
5859
}
59-
for (int bccid = 0; bccid < cc.num_bccs; bccid++) {
60+
for (int bccid = 0; bccid < num_bccs; bccid++) {
6061
assert(
6162
sz(bcc_to_nodes[bccid]) == sz(bvt[bccid + n]));
6263
for (auto u : bvt[bccid + n])
@@ -66,8 +67,8 @@ int main() {
6667
vector<int> lone_nodes;
6768
for (int u = 0; u < n; u++)
6869
if (empty(bvt[u])) lone_nodes.push_back(u);
69-
cout << cc.num_bccs + sz(lone_nodes) << '\n';
70-
for (int bccid = 0; bccid < cc.num_bccs; bccid++) {
70+
cout << num_bccs + sz(lone_nodes) << '\n';
71+
for (int bccid = 0; bccid < num_bccs; bccid++) {
7172
cout << sz(bvt[bccid + n]) << " ";
7273
for (auto u : bvt[bccid + n]) cout << u << " ";
7374
cout << '\n';

0 commit comments

Comments
 (0)