https://yukicoder.me/problems/no/901
前提知識
解説
https://yukicoder.me/submissions/387110
この問題の上位互換であるが、本質的には同じ解法を使える。
与えられた頂点をEuler Tourでの順番にソートすると、(v1->v2の距離+v2->v3の距離+...+vN->v1の距離)/2が答えになる。
これはv1->v2->...->vN->v1とすると、辺をちょうど2回だけ通るパスになるためである。
ちょうど2回通る理由としては、Euler TourはDFSで順番に遷移していて、
その順番に並び替えたということは、DFSで訪れるパスのうち一部を削除した形になるためである。
int N; vector<pair<int, int>> E[101010]; int Q; //--------------------------------------------------------------------------------------------------- HLDecomposition hld; ll sm[101010]; void dfs(int cu, int pa = -1) { fore(p, E[cu]) { int to, c; tie(to, c) = p; if (pa == to) continue; sm[to] = sm[cu] + c; dfs(to, cu); } } ll get(int a, int b) { return sm[a] + sm[b] - 2LL * sm[hld.lca(a, b)]; } //--------------------------------------------------------------------------------------------------- void _main() { cin >> N; hld.init(N); rep(i, 0, N - 1) { int a, b, c; cin >> a >> b >> c; E[a].push_back({b, c}); E[b].push_back({a, c}); hld.add(a, b); } hld.build(); dfs(0); cin >> Q; rep(q, 0, Q) { int k; cin >> k; vector<pair<int, int>> v; rep(i, 0, k) { int x; cin >> x; v.push_back({hld.vid[x], x}); } sort(all(v)); ll ans = 0; int n = v.size(); rep(i, 0, n) ans += get(v[i].second, v[(i + 1) % n].second); ans /= 2; printf("%lld\n", ans); } }