T on #10。
用的对 dfn 排序求 lca 的建树方法,因为人傻,所以常熟很大,求卡常。
#include <bits/stdc++.h>
#define ll long long
#define F first
#define S second
const int N = 2.5e5 + 10, M = 2e5 + 10, inf = 1e9;
inline int read() {
int x = 0, f = 1; char ch = getchar();
for (; ch < '0' || ch > '9'; ch = getchar()) if (ch == '-') f = -1;
for (; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
return x * f;
}
void write( int x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
using namespace std;
int n, m;
ll dp[N];
int h[N], vis[N];
vector< pair< int, int> > G[N], Gv[N];
int fa[21][N], mi[21][N], dep[N], dfn[N];
int tot;
void dfs( int u, int fu, int w) {
dfn[u] = ++ tot, dep[u] = dep[fu] + 1, fa[0][u] = fu, mi[0][u] = w;
for ( int i = 1; i < 21; i ++) fa[i][u] = fa[i - 1][fa[i - 1][u]];
for ( int i = 1; i < 21; i ++) mi[i][u] = min(mi[i - 1][u], mi[i - 1][fa[i - 1][u]]);
for ( auto i : G[u]) if (i.F != fu) dfs(i.F, u, i.S);
}
pair< int, int> query( int u, int v) {
int res = inf;
if (dep[u] < dep[v]) swap(u, v);
for ( int i = 20; i >= 0; i --)
if (dep[fa[i][u]] >= dep[v]) res = min(res, mi[i][u]), u = fa[i][u];
if (u == v) return {u, res};
for ( int i = 20; i >= 0; i --) if (fa[i][u] != fa[i][v])
res = min(res, min(mi[i][u], mi[i][v])), u = fa[i][u], v = fa[i][v];
res = min(res, min(mi[0][u], mi[0][v]));
return {fa[0][u], res};
}
int tr[N], len;
int cmp( int a, int b) { return dfn[a] < dfn[b]; }
void build( int k) {
len = 0;
for ( register int i = 1; i <= k; i ++) tr[++ len] = h[i];
tr[++ len] = 1;
sort(tr + 1, tr + k + 1, cmp), len = unique(tr + 1, tr + len + 1) - tr - 1;
for ( register int i = 1; i < k; i ++) tr[++ len] = query(tr[i], tr[i + 1]).F;
sort(tr + 1, tr + len + 1, cmp), len = unique(tr + 1, tr + len + 1) - tr - 1;
for ( register int i = 1; i < len; i ++) {
auto res = query(tr[i], tr[i + 1]);
int res2 = query(res.F, tr[i + 1]).S;
Gv[res.F].push_back({tr[i + 1], res2});
}
function< void( int, int)> solve = [&]( int u, int fu) {
dp[u] = 0;
for ( auto i : Gv[u]) {
int v = i.F, w = i.S;
if (v == fu) continue ;
solve(v, u);
if (vis[v]) dp[u] += w; else dp[u] += min(dp[v], 1ll * w);
}
} ;
solve(1, 0);
for ( int i = 1; i <= len; i ++) Gv[tr[i]].clear();
}
signed main() {
n = read();
for ( int i = 1, u, v, w; i < n; i ++) {
u = read(), v = read(), w = read();
G[u].push_back({v, w}), G[v].push_back({u, w});
}
memset(mi, 127, sizeof mi);
dep[0] = 1;
dfs(1, 0, inf);
m = read();
while (m --) {
int k = read();
for ( int i = 1; i <= k; i ++) h[i] = read(), vis[h[i]] = 1;
build(k);
printf("%lld\n", dp[1]);
for ( int i = 1; i <= k; i ++) vis[h[i]] = 0;
}
}