-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathdominator_tree.cpp
120 lines (112 loc) · 2.94 KB
/
dominator_tree.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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
struct DominatorTree {
int n;
int root;
vector<int> tin, revin;
vector<int> sdom, idom;
vector<vector<int>> g, revg;
vector<int> parent;
vector<int> dsu;
vector<int> min_v;
int cnt = 0;
int get(int v) {
++cnt;
if (dsu[v] == v) {
return v;
}
int next_v = get(dsu[v]);
if (sdom[min_v[dsu[v]]] < sdom[min_v[v]]) {
min_v[v] = min_v[dsu[v]];
}
dsu[v] = next_v;
return next_v;
}
void merge(int from, int to) {
dsu[from] = to;
}
DominatorTree(int n, int root): n(n), root(root), dsu(n) {
tin.resize(n, -1);
revin.resize(n, -1);
sdom.resize(n);
idom.resize(n);
g.resize(n);
revg.resize(n);
dsu.resize(n);
parent.assign(n, -1);
min_v.assign(n, -1);
for (int i = 0; i < n; ++i) {
dsu[i] = i;
min_v[i] = i;
sdom[i] = i;
idom[i] = i;
}
}
void dfs(int v, vector<vector<int>>& cur_g, int& timer) {
tin[v] = timer++;
for (int to : cur_g[v]) {
if (tin[to] == -1) {
dfs(to, cur_g, timer);
parent[tin[to]] = tin[v];
}
revg[tin[to]].push_back(tin[v]);
}
}
vector<int> get_tree(vector<vector<int>> cur_g) {
vector<char> used(n, false);
int timer = 0;
dfs(root, cur_g, timer);
for (int i = 0; i < n; ++i) {
if (tin[i] == -1) {
continue;
}
revin[tin[i]] = i;
for (int to : cur_g[i]) {
g[tin[i]].push_back(tin[to]);
}
}
vector<vector<int>> buckets(n);
for (int i = n - 1; i >= 0; --i) {
for (int to : revg[i]) {
get(to);
sdom[i] = min(sdom[i], sdom[min_v[to]]);
}
if (revin[i] == -1) {
continue;
}
if (i) {
buckets[sdom[i]].push_back(i);
}
for (int w : buckets[i]) {
get(w);
int v = min_v[w];
if (sdom[v] == sdom[w]) {
idom[w] = sdom[w];
} else {
idom[w] = v;
}
}
for (int to : g[i]) {
if (parent[to] == i) {
merge(to, i);
}
}
}
for (int i = 0; i < n; ++i) {
if (revin[i] == -1) {
continue;
}
if (idom[i] == sdom[i]) {
continue;
} else {
idom[i] = idom[idom[i]];
}
}
vector<int> res(n, -1);
for (int i = 0; i < n; ++i) {
if (revin[i] == -1) {
continue;
}
res[revin[i]] = revin[idom[i]];
}
return res;
}
};