-
Notifications
You must be signed in to change notification settings - Fork 39
/
strongly_connected.cpp
77 lines (62 loc) · 1.56 KB
/
strongly_connected.cpp
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
// Strongly connected components decomposition algorithm
//
// Usage:
// Initialize with constructor as the number of nodes
// and add edges accordingly with the AddEdge(u, v) method.
// Then just run Reduce()
//
// ATTENTION: The reduced DAG may contain duplicate edges
struct SCCWrapper {
int n;
vector<vector<int>> G, G_T;
vector<bool> Viz;
vector<int> Stack;
vector<int> SCC; // SCC[i] gives the scc id of node i
vector<vector<int>> Nodes; // Nodes[i] is the list of nodes in scc i
vector<vector<int>> G_R; // The reduced DAG (MAY CONTAIN DUPLICATE EDGES)
int scc; // Strongly connected component count
SCCWrapper(int n) : n(n), Viz(n), G(n), G_T(n), SCC(n) {
Stack.reserve(n);
scc = 0;
};
void AddEdge(int a, int b) {
G[a].push_back(b);
G_T[b].push_back(a);
}
void dfs_forward(int node) {
Viz[node] = true;
for(auto vec : G[node]) {
if(!Viz[vec])
dfs_forward(vec);
}
Stack.push_back(node);
}
void dfs_backward(int node) {
Viz[node] = true;
SCC[node] = scc;
Nodes[scc].push_back(node);
for(auto vec : G_T[node]) {
if(!Viz[vec])
dfs_backward(vec);
}
}
void Reduce() {
fill(Viz.begin(), Viz.end(), 0);
for(int i = 0; i < n; ++i)
if(!Viz[i])
dfs_forward(i);
assert(Stack.size() == n);
fill(Viz.begin(), Viz.end(), 0);
for(int i = n - 1; i >= 0; --i)
if(!Viz[Stack[i]]) {
Nodes.push_back(vector<int>());
dfs_backward(Stack[i]);
++scc;
}
G_R.resize(scc);
for(int i = 0; i < n; ++i) {
for(auto vec : G[i])
G_R[SCC[i]].push_back(SCC[vec]);
}
}
};