-
如果关键节点比较少,可以用虚树,把非关键节点的链化成边或删去
-
例题 : luogu P2495 [SDOI2011]消耗战
#include <cstdio>
#include <cstring>
#include <algorithm>
typedef long long ll;
const int N = 2.5e5 + 5;
int read(int x = 0, int f = 1, char c = getchar()) {
for (; c < '0' || c > '9'; c = getchar())
if (c == '-') f = -1;
for (; c >='0' && c <='9'; c = getchar())
x = x * 10 + c - '0';
return x * f;
}
struct Edge {
int n, t, d;
}e[N*2];
int h[N], edc;
void Add(int x, int y, int z = 0) {
e[++edc] = (Edge) {h[x], y, z}; h[x] = edc;
}
int n, fa[N], dep[N], son[N], sz[N], tp[N], dfn[N], dfc, a[N], stk[N], top;
bool v[N];
ll d[N];
void Dfs(int x) {
sz[x] = 1; dep[x] = dep[fa[x]] + 1;
for (int i = h[x], y; i; i = e[i].n) {
if ((y = e[i].t) == fa[x]) continue;
d[y] = std::min(d[x], (ll)e[i].d);
fa[y] = x; Dfs(y); sz[x] += sz[y];
if (!son[x] || sz[son[x]] < sz[y]) son[x] = y;
}
}
void Dfs(int x, int top) {
tp[x] = top; dfn[x] = ++dfc;
if (son[x]) Dfs(son[x], top);
for (int i = h[x], y; i; i = e[i].n)
if ((y = e[i].t) != fa[x] && y != son[x]) Dfs(y, y);
}
bool Cmp(const int &a, const int &b) {
return dfn[a] < dfn[b];
}
int Lca(int x, int y) {
while (tp[x] != tp[y])
dep[tp[x]] > dep[tp[y]] ? x = fa[tp[x]] : y = fa[tp[y]];
return dep[x] < dep[y] ? x : y;
}
ll Cal(int x) {
ll ans = 0;
for (int i = h[x], y; i; i = e[i].n)
ans += Cal(e[i].t);
if (v[x]) ans = d[x];
else ans = std::min(d[x], ans);
v[x] = h[x] = 0;
return ans;
}
int main() {
n = read();
for (int i = 1; i < n; ++i) {
int x = read(), y = read(), z = read();
Add(x, y, z); Add(y, x, z);
}
d[1] = 1e18; Dfs(1); Dfs(1, 1);
memset(h + 1, 0, n * 4); edc = 0;
for (int m = read(); m; --m) {
int k = read();
for (int i = 1; i <= k; ++i) a[i] = read();
std::sort(a + 1, a + k + 1, Cmp);
stk[top = 1] = 1;
for (int i = 1; i <= k; ++i) {
int lca = Lca(stk[top], a[i]); v[a[i]] = 1;
if (lca == stk[top]) { stk[++top] = a[i]; continue; }
for (; top > 1 && dep[stk[top]] > dep[lca]; --top)
Add(dep[stk[top-1]] > dep[lca] ? stk[top-1] : lca, stk[top]);
if (dep[lca] > dep[stk[top]]) stk[++top] = lca;
stk[++top] = a[i];
}
while (top > 1) Add(stk[top-1], stk[top]), top--;
printf("%lld
", Cal(1)); edc = 0;
}
return 0;
}