forked from the-tourist/algo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdominators.cpp
69 lines (69 loc) · 1.71 KB
/
dominators.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
template <typename T>
vector<int> find_dominators(const digraph<T> &g, int root) {
int n = g.n;
vector<int> pos(n, -1);
vector<int> order;
vector<int> parent(n, -1);
function<void(int)> dfs = [&g, &pos, &order, &parent, &dfs](int v) {
pos[v] = (int) order.size();
order.push_back(v);
for (int id : g.g[v]) {
auto &e = g.edges[id];
int u = e.to;
if (pos[u] == -1) {
parent[u] = v;
dfs(u);
}
}
};
dfs(root);
vector<int> p(n), best(n);
iota(p.begin(), p.end(), 0);
iota(best.begin(), best.end(), 0);
vector<int> sdom = pos;
function<int(int)> find_best = [&p, &best, &sdom, &find_best](int x) {
if (p[x] != x) {
int u = find_best(p[x]);
if (sdom[u] < sdom[best[x]]) {
best[x] = u;
}
p[x] = p[p[x]];
}
if (sdom[best[p[x]]] < sdom[best[x]]) {
best[x] = best[p[x]];
}
return best[x];
};
digraph<int> g_rev = g.reverse();
vector<int> idom(n, -1);
vector<int> link(n, 0);
vector<vector<int>> bucket(n);
for (int it = (int) order.size() - 1; it >= 0; it--) {
int w = order[it];
for (int id : g_rev.g[w]) {
auto &e = g_rev.edges[id];
int u = e.to;
if (pos[u] != -1) {
sdom[w] = min(sdom[w], sdom[find_best(u)]);
}
}
idom[w] = order[sdom[w]];
for (int u : bucket[w]) {
link[u] = find_best(u);
}
for (int id : g.g[w]) {
auto &e = g.edges[id];
int u = e.to;
if (parent[u] == w) {
p[u] = w;
}
}
bucket[order[sdom[w]]].push_back(w);
}
for (int it = 1; it < (int) order.size(); it++) {
int w = order[it];
idom[w] = idom[link[w]];
}
return idom;
// idom[i] -- immediate dominator for vertex i
}