in src/sizes/dominator_tree.cpp [48:124]
jlongs calculateRetainedSizesViaDominatorTree(const graph_t &graph, const jlongs &sizes) {
auto n = static_cast<jlong>(graph.size());
jlongs semi(n);
jlongs parent(n);
jlongs vertex(n);
jlongs ancestor(n);
jlongs label(n);
jlongs dom(n);
jlongs retainedSizes(n);
graph_t pred(n);
graph_t bucket(n);
for (jlong i = 0; i < n; i++) {
retainedSizes[i] = sizes[i];
label[i] = i;
ancestor[i] = -1;
}
n = 0;
dfs(0, n, graph, semi, parent, vertex, pred);
for (jlong i = n - 1; i > 0; i--) {
jlong w = vertex[i];
for (jlong v : pred[w]) {
jlong u = eval(v, ancestor, label, semi);
if (semi[u] < semi[w]) {
semi[w] = semi[u];
}
}
bucket[vertex[semi[w]]].push_back(w);
link(parent[w], w, ancestor);
for (jlong v : bucket[parent[w]]) {
jlong u = eval(v, ancestor, label, semi);
if (semi[u] < semi[v]) {
dom[v] = u;
} else {
dom[v] = parent[w];
}
}
bucket[parent[w]].clear();
}
dom[0] = -1;
jlongs childCount(n);
for (jlong i = 1; i < n; i++) {
jlong w = vertex[i];
if (dom[w] != vertex[semi[w]]) {
dom[w] = dom[dom[w]];
}
if (dom[w] >= 0) {
childCount[dom[w]]++;
}
}
std::queue<jlong> leaves;
for (jlong i = 1; i < n; i++) {
if (childCount[i] == 0) {
leaves.push(i);
}
}
while (!leaves.empty()) {
jlong leaf = leaves.front();
leaves.pop();
jlong d = dom[leaf];
if (d >= 0) {
retainedSizes[d] += retainedSizes[leaf];
if (--childCount[d] == 0) {
leaves.push(d);
}
}
}
return retainedSizes;
}