1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
| #include <bits/stdc++.h>
#define int int64_t
using pii = std::pair<int, int>;
const int kMaxN = 1e5 + 5, kMaxQ = 5e5 + 5;
int n, q, pos; int res[kMaxQ]; std::vector<std::pair<int, int>> qq[kMaxN];
struct Tree { int dfn_cnt, dfn[kMaxN], idx[kMaxN], sz[kMaxN], dis[kMaxN], st[kMaxN][18]; std::vector<std::pair<int, int>> G[kMaxN]; int get(int x, int y) { return dfn[x] < dfn[y] ? x : y; } void add(int u, int v, int w) { G[u].emplace_back(v, w), G[v].emplace_back(u, w); } void dfs(int u, int fa) { st[dfn[u] = ++dfn_cnt][0] = fa, idx[dfn_cnt] = u, sz[u] = 1; for (auto [v, w] : G[u]) { if (v == fa) continue; dis[v] = dis[u] + w; dfs(v, u); sz[u] += sz[v]; } } int LCA(int x, int y) { if (x == y) return x; if (dfn[x] > dfn[y]) std::swap(x, y); int k = std::__lg(dfn[y] - dfn[x]); return get(st[dfn[x] + 1][k], st[dfn[y] - (1 << k) + 1][k]); } int getdis(int x, int y) { return dis[x] + dis[y] - 2 * dis[LCA(x, y)]; } void prework() { dfn_cnt = 0, dfs(1, 0); for (int i = 1; i <= std::__lg(dfn_cnt); ++i) for (int j = 1; j <= dfn_cnt - (1 << i) + 1; ++j) st[j][i] = get(st[j][i - 1], st[j + (1 << (i - 1))][i - 1]); } } t1, t2;
int calc(int x, int y) { return t1.getdis(pos, x) + t1.getdis(pos, y) + t2.getdis(x, y); }
pii merge(pii a, pii b) { if (!a.first) return b; if (!b.first) return a; std::vector<int> vec = {a.first, a.second, b.first, b.second}; pii ret = {0, 0}; int now = -1e9; for (int i = 0; i < 4; ++i) { for (int j = i + 1; j < 4; ++j) { int val = calc(vec[i], vec[j]); if (val > now) ret = {vec[i], vec[j]}, now = val; } } return ret; }
struct SGT { pii t[kMaxN * 4]; void pushup(int x) { t[x] = merge(t[x << 1], t[x << 1 | 1]); } void build(int x, int l, int r) { if (l == r) return void(t[x] = {t1.idx[l], t1.idx[l]}); int mid = (l + r) >> 1; build(x << 1, l, mid), build(x << 1 | 1, mid + 1, r); pushup(x); } void update(int x, int l, int r, int ql, int qr) { if (l > qr || r < ql) return; else if (l >= ql && r <= qr) return; int mid = (l + r) >> 1; update(x << 1, l, mid, ql, qr), update(x << 1 | 1, mid + 1, r, ql, qr); pushup(x); } } sgt;
void dfs(int u, int fa) { for (auto [b, id] : qq[u]) { auto [x, y] = sgt.t[1]; res[id] = std::max({res[id], t1.getdis(x, u) + t2.getdis(x, b), t1.getdis(y, u) + t2.getdis(y, b)}); } for (auto [v, w] : t1.G[u]) { if (v == fa) continue; pos = v, sgt.update(1, 1, n, t1.dfn[v], t1.dfn[v] + t1.sz[v] - 1); dfs(v, u); pos = u, sgt.update(1, 1, n, t1.dfn[v], t1.dfn[v] + t1.sz[v] - 1); } }
void dickdreamer() { std::cin >> n >> q; for (int i = 1; i < n; ++i) { int u, v, w; std::cin >> u >> v >> w; t1.add(u, v, w); } for (int i = 1; i < n; ++i) { int u, v, w; std::cin >> u >> v >> w; t2.add(u, v, w); } for (int i = 1; i <= q; ++i) { int a, b; std::cin >> a >> b; qq[a].emplace_back(b, i); } t1.prework(), t2.prework(); pos = 1, sgt.build(1, 1, n); dfs(1, 0); for (int i = 1; i <= q; ++i) std::cout << res[i] << '\n'; }
int32_t main() { #ifdef ORZXKR freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0); int T = 1; while (T--) dickdreamer(); return 0; }
|