From d9a61d211b3f9ab45c7787f399efa59ffe9e4bff Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Tue, 6 Aug 2024 17:36:36 +0900 Subject: [PATCH] weighted lca --- cpp/tree.hpp | 31 ++++++++++++++++++++++++++++--- test/yukicoder-898.test.cpp | 22 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 test/yukicoder-898.test.cpp diff --git a/cpp/tree.hpp b/cpp/tree.hpp index 26e00b4..7ffd8b4 100644 --- a/cpp/tree.hpp +++ b/cpp/tree.hpp @@ -135,7 +135,6 @@ struct RootedTree : private Tree { using Tree::operator[]; using Tree::edges; using Tree::shortest_path; - using Tree::Tree; int root; //!< 根 std::vector par; //!< 親へ向かう辺 @@ -262,7 +261,6 @@ struct DoublingClimbTree : private RootedTree { using RootedTree::operator[]; using RootedTree::edges; using RootedTree::shortest_path; - using RootedTree::RootedTree; using RootedTree::root; using RootedTree::par; using RootedTree::child; @@ -296,6 +294,34 @@ struct DoublingClimbTree : private RootedTree { build(); } + /** + * @brief 親の頂点のリストから根が0のダブリング済み根付き木を構築するコンストラクタ + * + * @param par_ 頂点0以外の親の頂点のリスト + * @param padding = -1 parの頂点番号をいくつずらすか + */ + DoublingClimbTree(const std::vector& par_, int padding = -1) : RootedTree(par_, padding) { + build(); + } + /** + * @brief Treeからダブリング済み根付き木を構築するコンストラクタ(コピー) + * + * @param tree Tree + * @param root 根 + */ + DoublingClimbTree(const Tree& tree, int root) : RootedTree(tree, root) { + build(); + } + /** + * @brief Treeからダブリング済み根付き木を構築するコンストラクタ(ムーブ) + * + * @param tree Tree + * @param root 根 + */ + DoublingClimbTree(Tree&& tree, int root) : RootedTree(std::move(tree), root) { + build(); + } + /** * @brief 頂点uからk回を根の方向に遡った頂点 * @@ -321,7 +347,6 @@ struct DoublingClimbTree : private RootedTree { int lca(int u, int v) const { if(this->unweighted_depth[u] > this->unweighted_depth[v]) std::swap(u, v); v = climb(v, this->unweighted_depth[v] - this->unweighted_depth[u]); - if(this->unweighted_depth[u] > this->unweighted_depth[v]) u = climb(u, this->unweighted_depth[u] - this->unweighted_depth[v]); if(u == v) return u; for(int i = h - 1; i >= 0; i--) { int nu = doubling_par[i][u]; diff --git a/test/yukicoder-898.test.cpp b/test/yukicoder-898.test.cpp new file mode 100644 index 0000000..aa54015 --- /dev/null +++ b/test/yukicoder-898.test.cpp @@ -0,0 +1,22 @@ +#define PROBLEM "https://yukicoder.me/problems/no/898" + +#include "../cpp/tree.hpp" +#include +using namespace std; +using ll = long long; + +int main() { + int n; cin >> n; + Tree tr(n); tr.read(0, true); + DoublingClimbTree dct(tr, 0); + int q; cin >> q; + while(q--) { + array xyz; + for(int i = 0; i < 3; i++) cin >> xyz[i]; + int lca01 = dct.lca(xyz[0], xyz[1]); + int lca02 = dct.lca(xyz[0], xyz[2]); + int lca12 = dct.lca(xyz[1], xyz[2]); + int center = lca01 ^ lca02 ^ lca12; + cout << dct.dist(xyz[0], center) + dct.dist(xyz[1], center) + dct.dist(xyz[2], center) << endl; + } +}