This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub HyunjaeLee/Algorithms
#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/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/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] << ' '; } }