Skip to content

Commit

Permalink
weighted lca
Browse files Browse the repository at this point in the history
  • Loading branch information
KowerKoint committed Aug 6, 2024
1 parent 865343f commit d9a61d2
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 3 deletions.
31 changes: 28 additions & 3 deletions cpp/tree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ struct RootedTree : private Tree<Cost> {
using Tree<Cost>::operator[];
using Tree<Cost>::edges;
using Tree<Cost>::shortest_path;
using Tree<Cost>::Tree;

int root; //!< 根
std::vector<Edge> par; //!< 親へ向かう辺
Expand Down Expand Up @@ -262,7 +261,6 @@ struct DoublingClimbTree : private RootedTree<Cost> {
using RootedTree<Cost>::operator[];
using RootedTree<Cost>::edges;
using RootedTree<Cost>::shortest_path;
using RootedTree<Cost>::RootedTree;
using RootedTree<Cost>::root;
using RootedTree<Cost>::par;
using RootedTree<Cost>::child;
Expand Down Expand Up @@ -296,6 +294,34 @@ struct DoublingClimbTree : private RootedTree<Cost> {
build();
}

/**
* @brief 親の頂点のリストから根が0のダブリング済み根付き木を構築するコンストラクタ
*
* @param par_ 頂点0以外の親の頂点のリスト
* @param padding = -1 parの頂点番号をいくつずらすか
*/
DoublingClimbTree(const std::vector<int>& par_, int padding = -1) : RootedTree<Cost>(par_, padding) {
build();
}
/**
* @brief Treeからダブリング済み根付き木を構築するコンストラクタ(コピー)
*
* @param tree Tree
* @param root 根
*/
DoublingClimbTree(const Tree<Cost>& tree, int root) : RootedTree<Cost>(tree, root) {
build();
}
/**
* @brief Treeからダブリング済み根付き木を構築するコンストラクタ(ムーブ)
*
* @param tree Tree
* @param root 根
*/
DoublingClimbTree(Tree<Cost>&& tree, int root) : RootedTree<Cost>(std::move(tree), root) {
build();
}

/**
* @brief 頂点uからk回を根の方向に遡った頂点
*
Expand All @@ -321,7 +347,6 @@ struct DoublingClimbTree : private RootedTree<Cost> {
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];
Expand Down
22 changes: 22 additions & 0 deletions test/yukicoder-898.test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#define PROBLEM "https://yukicoder.me/problems/no/898"

#include "../cpp/tree.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

int main() {
int n; cin >> n;
Tree<ll> tr(n); tr.read(0, true);
DoublingClimbTree<ll> dct(tr, 0);
int q; cin >> q;
while(q--) {
array<int, 3> 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;
}
}

0 comments on commit d9a61d2

Please sign in to comment.