This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "https://judge.yosupo.jp/problem/dominatortree"
#include "graph/dominator_tree.hpp"
#include <bits/stdc++.h>
int main() {
std::cin.tie(0)->sync_with_stdio(0);
int N, M, S;
std::cin >> N >> M >> S;
dominator_tree dt(N);
for (auto i = 0; i < M; ++i) {
int a, b;
std::cin >> a >> b;
dt.add_edge(a, b);
}
dt.run(S);
for (auto i = 0; i < N; ++i) {
std::cout << dt[i] << ' ';
}
}#line 1 "test/graph/dominator_tree.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/dominatortree"
#line 1 "graph/dominator_tree.hpp"
#include <algorithm>
#include <cassert>
#include <numeric>
#include <vector>
struct dominator_tree {
explicit dominator_tree(int n)
: n_(n), parent_(n), idom_(n, -1), sdom_(n, -1), dsu_(n), label_(n),
graph_(n), rev_graph_(n) {
order_.reserve(n);
std::iota(dsu_.begin(), dsu_.end(), 0);
std::iota(label_.begin(), label_.end(), 0);
}
void add_edge(int from, int to) {
assert(0 <= from && from < n_ && 0 <= to && to < n_);
graph_[from].push_back(to);
rev_graph_[to].push_back(from);
}
void run(int root) {
assert(0 <= root && root < n_);
dfs(root);
std::vector<std::vector<int>> bucket(n_);
std::vector<int> x(n_);
for (auto i = static_cast<int>(order_.size()) - 1; i >= 0; --i) {
auto u = order_[i];
for (auto v : rev_graph_[u]) {
if (~sdom_[v]) {
sdom_[u] = std::min(sdom_[u], sdom_[eval(v)]);
}
}
bucket[order_[sdom_[u]]].push_back(u);
for (auto v : bucket[parent_[u]]) {
x[v] = eval(v);
}
bucket[parent_[u]].clear();
link(parent_[u], u);
}
for (auto i = 1; i < static_cast<int>(order_.size()); ++i) {
auto u = order_[i], v = x[u];
idom_[u] = (sdom_[u] == sdom_[v] ? sdom_[u] : idom_[v]);
}
for (auto i = 1; i < static_cast<int>(order_.size()); ++i) {
auto u = order_[i];
idom_[u] = order_[idom_[u]];
}
idom_[root] = root;
}
int operator[](int u) const {
assert(0 <= u && u < n_);
return idom_[u];
}
private:
void dfs(int u) {
sdom_[u] = static_cast<int>(order_.size());
order_.push_back(u);
for (auto v : graph_[u]) {
if (!~sdom_[v]) {
parent_[v] = u;
dfs(v);
}
}
}
int find(int u) {
if (dsu_[u] == u) {
return u;
}
auto root = find(dsu_[u]);
if (sdom_[label_[u]] > sdom_[label_[dsu_[u]]]) {
label_[u] = label_[dsu_[u]];
}
return dsu_[u] = root;
}
int eval(int u) {
find(u);
return label_[u];
}
void link(int u, int v) { dsu_[v] = u; }
int n_;
std::vector<int> order_, parent_, idom_, sdom_, dsu_, label_;
std::vector<std::vector<int>> graph_, rev_graph_;
};
#line 4 "test/graph/dominator_tree.test.cpp"
#include <bits/stdc++.h>
int main() {
std::cin.tie(0)->sync_with_stdio(0);
int N, M, S;
std::cin >> N >> M >> S;
dominator_tree dt(N);
for (auto i = 0; i < M; ++i) {
int a, b;
std::cin >> a >> b;
dt.add_edge(a, b);
}
dt.run(S);
for (auto i = 0; i < N; ++i) {
std::cout << dt[i] << ' ';
}
}