2
2
using namespace std ;
3
3
#define pii pair<int ,int >
4
4
5
- const int MAXN = 1e6 + 5 ;
6
- const int MAXM = 1e6 + 5 ;// Cuidado
7
-
8
- vector<pii> grafo [MAXN];
9
- int pre[MAXN], low[MAXN], clk=0 , C=0 ;
10
-
11
- vector<pii> edge;
12
- bool visEdge[MAXM];
13
- int edgeComponent[MAXM];
14
- int vertexComponent[MAXN];
15
-
16
- int cut[MAXN];
17
- stack<int > s;
18
-
19
- vector<int > tree [2 *MAXN];
20
- int componentSize[2 *MAXN]; // vertex - cutPoints
21
-
22
- void reset (int n){
23
- for (int i=0 ; i<=edge.size (); i++)
24
- visEdge[i] = edgeComponent[i] = 0 ;
25
-
26
- edge.clear ();
27
-
28
- for (int i=0 ; i<=n; i++){
29
- pre[i] = low[i] = -1 ;
30
- cut[i] = false ;
31
- vertexComponent[i] = 0 ;
32
- grafo[i].clear ();
33
- }
34
-
35
- for (int i=0 ; i<=C; i++){
36
- componentSize[i] = 0 ;
37
- tree[i].clear ();
38
- }
39
-
40
- while (!s.empty ()) s.pop ();
41
-
42
- clk = C = 0 ;
43
- }
44
-
45
- void newComponent (int i){
46
- C++;
47
- int j;
48
-
49
- do {
50
- j = s.top (); s.pop ();
51
- edgeComponent[j] = C;
52
-
53
- auto [u, v] = edge[j];
54
- if (!cut[u] && !vertexComponent[u]) componentSize[C]++, vertexComponent[u] = C;
55
- if (!cut[v] && !vertexComponent[v]) componentSize[C]++, vertexComponent[v] = C;
56
-
57
- } while (!s.empty () && j != i);
58
- }
59
-
60
- void tarjan (int u, bool root = true ){
61
- pre[u] = low[u] = clk++;
62
-
63
- bool any = false ;
64
- int chd = 0 ;
65
-
66
- for (auto [v, i] : grafo[u]){
67
- if (visEdge[i]) continue ;
68
- visEdge[i] = true ;
69
-
70
- s.emplace (i);
71
-
72
- if (pre[v] == -1 )
73
- {
74
- tarjan (v, false );
75
-
76
- low[u] = min (low[v], low[u]);
77
- chd++;
78
-
79
- if (!root && low[v] >= pre[u]) cut[u] = true , newComponent (i);
80
- if ( root && chd >= 2 ) cut[u] = true , newComponent (i);
81
- }
82
- else
83
- low[u] = min (low[u], pre[v]);
84
- }
85
-
86
- if (root) newComponent (-1 );
87
- }
88
-
89
- // ATENCAO: ESTA 1-INDEXADO
90
- void buildBCC (int n){
91
- vector<bool > marc (C+1 , false );
92
-
93
- for (int u=1 ; u<=n; u++)
94
- {
95
- if (!cut[u]) continue ;
96
-
97
- C++;
98
- cut[u] = C;
99
-
100
- for (auto [v, i] : grafo[u])
101
- {
102
- int ec = edgeComponent[i];
103
- if (!marc[ec])
104
- {
105
- marc[ec] = true ;
106
- tree[cut[u]].emplace_back (ec);
107
- tree[ec].emplace_back (cut[u]);
108
- }
109
- }
110
-
111
- for (auto [v, i] : grafo[u])
112
- marc[edgeComponent[i]] = false ;
113
- }
114
- }
115
-
116
- void addEdge (int u, int v){
117
- int i = edge.size ();
118
- grafo[u].emplace_back (v, i);
119
- grafo[v].emplace_back (u, i);
120
- edge.emplace_back (u, v);
121
- }
5
+ struct BlockCutTree {
6
+ vector<vector<int >> g, tree, comp;
7
+ vector<int > id, cut;
8
+ BlockCutTree (int n) : n(n), g(n), cut(n) {}
9
+
10
+ void addEdge (int u, int v){
11
+ g[u].emplace_back (v);
12
+ g[v].emplace_back (u);
13
+ }
14
+
15
+ void build (){
16
+ pre = low = id = vector<int >(n, -1 );
17
+ for (int u=0 ; u<n; u++, chd=0 ) if (pre[u] == -1 ) // if graph is disconected
18
+ tarjan (u, -1 ), makeComp (-1 ); // find cut vertex and make components
19
+
20
+ for (int i=0 , ct=1 ; i<comp.size (); i++, ct=1 ){ // remove components with only cuts
21
+ for (auto u : comp[i]) ct &= cut[u];
22
+ if (ct) swap (comp[i], comp.back ()), comp.pop_back (), i--;
23
+ }
24
+
25
+ for (int u=0 ; u<n; u++) if (cut[u]) comp.emplace_back (1 , u); // create cut components
26
+
27
+ for (int i=0 ; i<comp.size (); i++) // mark id of each node
28
+ for (auto u : comp[i])
29
+ id[u] = i;
30
+
31
+ tree.resize (comp.size ()); // creates tree (looking only edges from cut points)
32
+ pre.assign (comp.size (), 1 );
33
+
34
+ for (int u=0 ; u<n; u++) if (cut[u]){
35
+ for (auto v : g[u]) if (pre[id[v]] && (!cut[v] || u<v)) addt (id[u], id[v]), pre[id[v]]=0 ;
36
+ for (auto v : g[u]) pre[id[v]] = 1 ;
37
+ }
38
+ }
39
+ private:
40
+ vector<int > pre, low;
41
+ vector<pii> st;
42
+ int n, clk = 0 , chd=0 , ct, a, b;
43
+ void addt (int u, int v){
44
+ tree[u].push_back (v);
45
+ tree[v].push_back (u);
46
+ }
47
+
48
+ void makeComp (int u){
49
+ comp.emplace_back ();
50
+ do {
51
+ tie (a, b) = st.back ();
52
+ st.pop_back ();
53
+ comp.back ().push_back (b);
54
+ } while (a != u);
55
+ if (~u) comp.back ().push_back (u);
56
+ }
57
+
58
+ void tarjan (int u, int p){
59
+ pre[u] = low[u] = clk++;
60
+ st.emplace_back (p, u);
61
+
62
+ for (auto v : g[u]) if (v != p){
63
+ if (pre[v] == -1 ){
64
+ tarjan (v, u);
65
+ low[u] = min (low[u], low[v]);
66
+ cut[u] |= ct = (~p && low[v] >= pre[u]) || (p==-1 && ++chd >= 2 );
67
+ if (ct) makeComp (u);
68
+ }
69
+ else low[u] = min (low[u], pre[v]);
70
+ }
71
+ }
72
+ };
122
73
123
74
/* LATEX_DESC_BEGIN***************************
124
75
Block Cut Tree - BiConnected Component
125
-
126
- reset(n);
127
- addEdge(u, v);
128
- tarjan(Root);
129
- buildBCC(n);
130
-
131
- No fim o grafo da Block Cut Tree estara em _vector<int> tree []_
76
+ BlockCutTree bcc(n);
77
+ bcc.addEdge(u, v);
78
+ bcc.build();
79
+
80
+ bcc.tree -> graph of BlockCutTree
81
+ bcc.id[u] -> componet of u in the tree
82
+ bcc.cut[u] -> 1 if u is a cut vertex; 0 otherwise
83
+ bcc.comp[i] -> vertex of comp i (cut are part of multiple comp)
132
84
*****************************LATEX_DESC_END*/
0 commit comments