結果
| 問題 | No.1094 木登り / Climbing tree |
| ユーザー |
|
| 提出日時 | 2020-08-02 14:25:23 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.89.0) |
| 結果 |
AC
|
| 実行時間 | 525 ms / 2,000 ms |
| コード長 | 3,296 bytes |
| 記録 | |
| コンパイル時間 | 1,201 ms |
| コンパイル使用メモリ | 83,184 KB |
| 最終ジャッジ日時 | 2025-01-12 13:17:56 |
|
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 26 |
ソースコード
#include <iostream>
#include <vector>
template <class Cost = int>
struct Edge {
int src, dst;
Cost cost;
Edge(int src = -1, int dst = -1, Cost cost = 1)
: src(src), dst(dst), cost(cost){};
bool operator<(const Edge<Cost>& e) const { return this->cost < e.cost; }
bool operator>(const Edge<Cost>& e) const { return this->cost > e.cost; }
};
template <class Cost = int>
struct Graph {
std::vector<std::vector<Edge<Cost>>> graph;
Graph(int n = 0) : graph(n) {}
void span(bool direct, int src, int dst, Cost cost = 1) {
graph[src].emplace_back(src, dst, cost);
if (!direct) graph[dst].emplace_back(dst, src, cost);
}
int size() const { return graph.size(); }
void clear() { graph.clear(); }
void resize(int n) { graph.resize(n); }
std::vector<Edge<Cost>>& operator[](int v) { return graph[v]; }
std::vector<Edge<Cost>> operator[](int v) const { return graph[v]; }
};
template <class Cost = int>
struct LevelAncestor {
Graph<Cost> tree;
std::vector<std::vector<int>> par;
std::vector<int> depth;
std::vector<Cost> cdepth;
int kmax;
void dfs(int v, int p = -1, int d = 0, Cost c = 0) {
par[v][0] = p;
depth[v] = d;
cdepth[v] = c;
for (const auto& e : tree[v]) {
if (e.dst == p) continue;
dfs(e.dst, v, d + 1, c + e.cost);
}
}
LevelAncestor(const Graph<Cost>& tree, int root)
: tree(tree), par(tree.size()), depth(tree.size(), -1), cdepth(tree.size()) {
kmax = 0;
while ((1 << kmax) < (int)tree.size()) ++kmax;
for (auto& v : par) v.resize(kmax + 1);
dfs(root);
for (int k = 1; k <= kmax; ++k) {
for (int v = 0; v < tree.size(); ++v) {
int p = par[v][k - 1];
par[v][k] = (p == -1 ? -1 : par[p][k - 1]);
}
}
}
int climb(int v, int d) const {
for (int k = kmax; k >= 0 && v != -1; --k) {
if ((1 << k) > d) continue;
v = par[v][k];
d -= (1 << k);
}
return v;
}
int lca(int u, int v) const {
if (depth[u] < depth[v]) std::swap(u, v);
if (depth[u] > depth[v]) {
u = climb(u, depth[u] - depth[v]);
}
if (u == v) return u;
for (int k = kmax; k >= 0; --k) {
if (par[u][k] != par[v][k]) {
u = par[u][k];
v = par[v][k];
}
}
return par[u][0];
}
int dist(int u, int v) const {
int p = lca(u, v);
return depth[u] + depth[v] - depth[p] * 2;
}
Cost cdist(int u, int v) const {
int p = lca(u, v);
return cdepth[u] + cdepth[v] - cdepth[p] * 2;
}
};
void solve() {
int n;
std::cin >> n;
Graph<int> graph(n);
for (int i = 0; i < n - 1; ++i) {
int u, v, c;
std::cin >> u >> v >> c;
graph.span(false, --u, --v, c);
}
LevelAncestor<int> la(graph, 0);
int q;
std::cin >> q;
while (q--) {
int u, v;
std::cin >> u >> v;
std::cout << la.cdist(--u, --v) << "\n";
}
}
int main() {
std::cin.tie(nullptr);
std::ios::sync_with_stdio(false);
solve();
return 0;
}