Euler tour (BFS)
(Mylib/Graph/TreeUtils/euler_tour_bfs.cpp)
Operations
EulerTourBFS(tree, int root)
-
query_children(int i, int d, f)
-
query_at(int i, f)
-
query_children(i, 0, f)
と同等。
-
get_parent
-
get_ancestor(int i, int k)
-
i
のk
個遡った祖先を返す。
get_ancestor(i, 0) = i
get_ancestor(i, 1) = get_parent(i)
- Time complexity $O(k)$
Requirements
Notes
Problems
References
Depends on
Verified with
Code
#pragma once
#include <queue>
#include <vector>
#include "Mylib/Graph/Template/graph.cpp"
namespace haar_lib {
template <typename T>
class euler_tour_bfs {
int N_;
std::vector<int> parent_, depth_, left_, right_;
std::vector<std::vector<int>> bfs_order_, dfs_order_;
public:
euler_tour_bfs() {}
euler_tour_bfs(const tree<T> &tr, int root) : N_(tr.size()), parent_(N_), depth_(N_), left_(N_), right_(N_) {
{
int ord = 0;
dfs(tr, root, -1, 0, ord);
}
{
std::queue<std::pair<int, int>> q;
q.emplace(root, 0);
int ord = 0;
while (not q.empty()) {
auto [i, d] = q.front();
q.pop();
if ((int) bfs_order_.size() <= d) bfs_order_.emplace_back();
bfs_order_[d].push_back(ord);
++ord;
for (auto &e : tr[i]) {
if (e.to == parent_[i]) continue;
q.emplace(e.to, d + 1);
}
}
}
}
private:
void dfs(const tree<T> &tr, int cur, int par, int d, int &ord) {
parent_[cur] = par;
depth_[cur] = d;
if ((int) dfs_order_.size() <= d) dfs_order_.emplace_back();
dfs_order_[d].push_back(ord);
left_[cur] = ord;
++ord;
for (auto &e : tr[cur]) {
if (e.to == par) continue;
dfs(tr, e.to, cur, d + 1, ord);
}
right_[cur] = ord;
}
public:
template <typename Func>
void query_children(int i, int d, const Func &f) const {
if (i != -1) {
d += depth_[i];
if ((int) bfs_order_.size() > d) {
int l = std::lower_bound(dfs_order_[d].begin(), dfs_order_[d].end(), left_[i]) - dfs_order_[d].begin();
int r = std::lower_bound(dfs_order_[d].begin(), dfs_order_[d].end(), right_[i]) - dfs_order_[d].begin();
if (l >= (int) bfs_order_[d].size()) return;
if (r == l) return;
f(bfs_order_[d][l], bfs_order_[d][r - 1] + 1);
}
}
}
template <typename Func>
void query_at(int i, const Func &f) const {
query_children(i, 0, f);
}
int get_parent(int i) const {
if (i == -1) return -1;
return parent_[i];
}
int get_ancestor(int i, int k) const {
int ret = i;
for (int i = 0; i < k; ++i) {
ret = get_parent(ret);
if (ret == -1) break;
}
return ret;
}
};
} // namespace haar_lib
#line 2 "Mylib/Graph/TreeUtils/euler_tour_bfs.cpp"
#include <queue>
#include <vector>
#line 2 "Mylib/Graph/Template/graph.cpp"
#include <iostream>
#line 4 "Mylib/Graph/Template/graph.cpp"
namespace haar_lib {
template <typename T>
struct edge {
int from, to;
T cost;
int index = -1;
edge() {}
edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
edge(int from, int to, T cost, int index) : from(from), to(to), cost(cost), index(index) {}
};
template <typename T>
struct graph {
using weight_type = T;
using edge_type = edge<T>;
std::vector<std::vector<edge<T>>> data;
auto& operator[](size_t i) { return data[i]; }
const auto& operator[](size_t i) const { return data[i]; }
auto begin() const { return data.begin(); }
auto end() const { return data.end(); }
graph() {}
graph(int N) : data(N) {}
bool empty() const { return data.empty(); }
int size() const { return data.size(); }
void add_edge(int i, int j, T w, int index = -1) {
data[i].emplace_back(i, j, w, index);
}
void add_undirected(int i, int j, T w, int index = -1) {
add_edge(i, j, w, index);
add_edge(j, i, w, index);
}
template <size_t I, bool DIRECTED = true, bool WEIGHTED = true>
void read(int M) {
for (int i = 0; i < M; ++i) {
int u, v;
std::cin >> u >> v;
u -= I;
v -= I;
T w = 1;
if (WEIGHTED) std::cin >> w;
if (DIRECTED)
add_edge(u, v, w, i);
else
add_undirected(u, v, w, i);
}
}
};
template <typename T>
using tree = graph<T>;
} // namespace haar_lib
#line 5 "Mylib/Graph/TreeUtils/euler_tour_bfs.cpp"
namespace haar_lib {
template <typename T>
class euler_tour_bfs {
int N_;
std::vector<int> parent_, depth_, left_, right_;
std::vector<std::vector<int>> bfs_order_, dfs_order_;
public:
euler_tour_bfs() {}
euler_tour_bfs(const tree<T> &tr, int root) : N_(tr.size()), parent_(N_), depth_(N_), left_(N_), right_(N_) {
{
int ord = 0;
dfs(tr, root, -1, 0, ord);
}
{
std::queue<std::pair<int, int>> q;
q.emplace(root, 0);
int ord = 0;
while (not q.empty()) {
auto [i, d] = q.front();
q.pop();
if ((int) bfs_order_.size() <= d) bfs_order_.emplace_back();
bfs_order_[d].push_back(ord);
++ord;
for (auto &e : tr[i]) {
if (e.to == parent_[i]) continue;
q.emplace(e.to, d + 1);
}
}
}
}
private:
void dfs(const tree<T> &tr, int cur, int par, int d, int &ord) {
parent_[cur] = par;
depth_[cur] = d;
if ((int) dfs_order_.size() <= d) dfs_order_.emplace_back();
dfs_order_[d].push_back(ord);
left_[cur] = ord;
++ord;
for (auto &e : tr[cur]) {
if (e.to == par) continue;
dfs(tr, e.to, cur, d + 1, ord);
}
right_[cur] = ord;
}
public:
template <typename Func>
void query_children(int i, int d, const Func &f) const {
if (i != -1) {
d += depth_[i];
if ((int) bfs_order_.size() > d) {
int l = std::lower_bound(dfs_order_[d].begin(), dfs_order_[d].end(), left_[i]) - dfs_order_[d].begin();
int r = std::lower_bound(dfs_order_[d].begin(), dfs_order_[d].end(), right_[i]) - dfs_order_[d].begin();
if (l >= (int) bfs_order_[d].size()) return;
if (r == l) return;
f(bfs_order_[d][l], bfs_order_[d][r - 1] + 1);
}
}
}
template <typename Func>
void query_at(int i, const Func &f) const {
query_children(i, 0, f);
}
int get_parent(int i) const {
if (i == -1) return -1;
return parent_[i];
}
int get_ancestor(int i, int k) const {
int ret = i;
for (int i = 0; i < k; ++i) {
ret = get_parent(ret);
if (ret == -1) break;
}
return ret;
}
};
} // namespace haar_lib
Back to top page