Repository navigation
Expand file tree
/
Copy pathBlock-Cut tree.cpp
More file actions
93 lines (83 loc) · 2.39 KB
/
Copy pathBlock-Cut tree.cpp
File metadata and controls
93 lines (83 loc) · 2.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*8<
* @Title: Block-Cut Tree
*
* @Description: Builds the Block-Cut of a undirected graph.
*
* @Time: $O(N+M)$
*
* @Usage: \textbf{$isGraphCutpoint[u]$} answers how many connected components
* are created when the node u is removed from the graph, if
* $isGraphCutpoint[u]$ is greater than $1$, it means that $u$ is a
* cutpoint.
*
* @Warning: Always careful with disconnected graphs ! you may end up having
* multiple trees.
*
* @Memory: $O(N)$
*
* @Time: $O(N+M)$
*
* @Problems:
* https://codeforces.com/group/btcK4I5D5f/contest/601720/problem/I
* >8*/
#pragma once
#include "../Contest/template.cpp"
struct BlockCutTree {
int n;
vi idOnTree, tin, low, stk, isGraphCutpoint, isTreeCutpoint;
vi2d comps, treeAdj;
BlockCutTree(vi2d &g)
: n(len(g)), idOnTree(n), tin(n), low(n), isGraphCutpoint(n) {
rep(i, 0, n) {
if (!tin[i]) {
int timer = 0;
dfs(i, -1, timer, g);
}
}
buildTree();
}
void buildTree() {
int node_id = 0;
rep(u, 0, n) {
if (isGraphCutpoint[u]) {
idOnTree[u] = node_id++;
isTreeCutpoint.eb(true);
treeAdj.pb({});
}
}
for (auto &comp : comps) {
int node = node_id++;
treeAdj.pb({});
isTreeCutpoint.eb(false);
for (int u : comp) {
if (!isGraphCutpoint[u]) {
idOnTree[u] = node;
} else {
treeAdj[node].eb(idOnTree[u]),
treeAdj[idOnTree[u]].eb(node);
}
}
}
}
void dfs(int u, int p, int &timer, vi2d &g) {
tin[u] = low[u] = ++timer;
stk.eb(u);
for (auto v : g[u]) {
if (v == p) continue;
if (!tin[v]) {
dfs(v, u, timer, g);
chmin(low[u], low[v]);
if (low[v] >= tin[u]) {
isGraphCutpoint[u] += (tin[u] > 1 or tin[v] > 2);
comps.pb({u});
while (comps.back().back() != v) {
comps.back().eb(stk.back());
stk.ppb();
}
}
} else
low[u] = min(low[u], tin[v]);
}
}
int countMandatoryNodesOnPath(int startNode, int endNode);
};