diff --git a/tree/virtual_tree.cpp b/old_impl/tree/virtual_tree.cpp similarity index 100% rename from tree/virtual_tree.cpp rename to old_impl/tree/virtual_tree.cpp diff --git a/tree/lca.hpp b/tree/lca.hpp index e8ed4d6..fb40238 100644 --- a/tree/lca.hpp +++ b/tree/lca.hpp @@ -6,7 +6,7 @@ class LCAUtils { int max_log, dfs_time; vector> par_up; - void dfs_lca(int u, int pr, int &dfs_time) { + void dfs_lca(int u, int pr, int& dfs_time) { in_time[u] = ++dfs_time; par_up[u][0] = pr; for(int i = 1; i < max_log; i++) { @@ -27,7 +27,13 @@ class LCAUtils { vector in_time, out_time; vector> adj; - LCAUtils() {} + LCAUtils() : n(0) {} + LCAUtils(int _n) { init(_n); } + LCAUtils(int _n, const vector>& _adj, int root = 0) { + init(_n); + adj = _adj; + prepare(root); + } void init(int _n) { n = _n; diff --git a/tree/lca_sparse_table.hpp b/tree/lca_sparse_table.hpp index 0dcfa32..583c125 100644 --- a/tree/lca_sparse_table.hpp +++ b/tree/lca_sparse_table.hpp @@ -29,6 +29,13 @@ class LCAUtilsRMQ { int n; vector> adj; + LCAUtilsRMQ() { n = 0; } + LCAUtilsRMQ(int _n) { init(_n); } + LCAUtilsRMQ(int _n, const vector>& _adj) { + init(_n); + adj = _adj; + } + void add_edge(int u, int v) { adj[u].push_back(v); adj[v].push_back(u); @@ -37,13 +44,13 @@ class LCAUtilsRMQ { void init(int _n) { n = _n; order.clear(); - adj.assign(n + 1, {}); + adj.assign(n, {}); } - void prepare(int root = 1) { + void prepare(int root = 0) { order.clear(); - pos.resize(n + 1); - dep.resize(n + 1); + pos.resize(n); + dep.resize(n); pre_dfs(root); rmq.init(order); } diff --git a/tree/virtual_tree.hpp b/tree/virtual_tree.hpp new file mode 100644 index 0000000..ed2260a --- /dev/null +++ b/tree/virtual_tree.hpp @@ -0,0 +1,59 @@ +#include +#include +using namespace std; + +class VirtualTree : public LCAUtils { + public: + VirtualTree() : LCAUtils() {} + VirtualTree(int n) : LCAUtils(n) {} + VirtualTree(int n, const vector>& adj, int root = 0) + : LCAUtils(n, adj, root) { + prepare(root); + } + + void add_edge(int u, int v) { LCAUtils::add_edge(u, v); } + + pair>, vector> build(const vector& vertices) { + if(vertices.empty()) { + return {{}, {}}; + } + + vector vec = vertices; + sort(vec.begin(), vec.end(), [&](int u, int v) { + return in_time[u] < in_time[v]; + }); + vec.erase(unique(vec.begin(), vec.end()), vec.end()); + + for(int i = (int)vec.size() - 1; i > 0; i--) { + vec.push_back(lca(vec[i - 1], vec[i])); + } + + sort(vec.begin(), vec.end(), [&](int u, int v) { + return in_time[u] < in_time[v]; + }); + vec.erase(unique(vec.begin(), vec.end()), vec.end()); + + vector> virtual_adj(vec.size()); + + stack s; + s.push(0); + for(int i = 1; i < (int)vec.size(); i++) { + while(!upper(vec[s.top()], vec[i])) { + int u = s.top(); + s.pop(); + int v = s.top(); + virtual_adj[v].push_back(u); + } + s.push(i); + } + + while(s.size() > 1) { + int u = s.top(); + s.pop(); + int v = s.top(); + virtual_adj[v].push_back(u); + } + + return {virtual_adj, vec}; + } +};