-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy path*TwoEdgeCCs.java
More file actions
88 lines (78 loc) · 1.65 KB
/
*TwoEdgeCCs.java
File metadata and controls
88 lines (78 loc) · 1.65 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
static class TwoEdgeCCs {
int n;
graph g;
int preCount, metaN, stkSize;
int[] pre, low, map, stk;
// returns forest meta graph
graph getMeta(graph gg) {
g = gg;
n = g.n;
// do lowlink
preCount = -1;
metaN = 0;
pre = new int[n];
Arrays.fill(pre, -1);
low = new int[n];
map = new int[n]; // maps each node in original graph g to new node index in meta
stk = new int[n];
stkSize = 0;
for(int i = 0; i < n; ++i) {
if(pre[i] == -1) dfs(i, -1);
}
graph meta = new graph(metaN);
for(int u = 0; u < n; ++u) {
for(edge e : g.edges[u]) {
// avoid adding edges twice
if(u < e.v && map[u] != map[e.v]) meta.addEdge(map[u], map[e.v], e.w);
}
}
return meta;
}
void dfs(int idx, int par) {
low[idx] = pre[idx] = ++preCount;
stk[stkSize++] = idx;
for(edge e : g.edges[idx]) {
if(e.v == par) continue;
// back edge
if(pre[e.v] != -1) {
if(pre[e.v] < low[idx]) low[idx] = pre[e.v];
continue;
}
dfs(e.v, idx);
if(low[e.v] < low[idx]) low[idx] = low[e.v];
// bridge
if(low[e.v] == pre[e.v]) pop(e.v);
}
if(par == -1 && stkSize > 0) pop(idx);
}
void pop(int stop) {
while(stkSize > 0) {
int curr = stk[--stkSize];
map[curr] = metaN;
if(curr == stop) break;
}
++metaN;
}
}
static class graph {
int n;
ArrayDeque<edge>[] edges;
graph(int nn){
edges = new ArrayDeque[n = nn];
for(int i = 0; i < n; ++i) edges[i] = new ArrayDeque<>();
}
void addEdge(int a, int b) {
addEdge(a, b, 1);
}
void addEdge(int a, int b, int w) {
edges[a].add(new edge(b, w));
edges[b].add(new edge(a, w));
}
}
static class edge{
int v, w;
edge(int vv, int ww){
v = vv;
w = ww;
}
}