P2495 消耗战
P2495 消耗战
虚树
虚树是一棵只保留询问关键点,非边变成链或剪掉的树,简化了原树的结构。
虚树常常在树形 DP 中,减少 DP 遍历的复杂度,对于含有 \(k\) 个点的询问,虚树最多有 \(k\) 个叶子结点,整颗虚树最多只有 \(2k−1\) 个结点。
void build(int n){//a 是关键点。
auto z = [&](int&i, int&j){return dfn[i] < dfn[j];};
a[++n] = 1, sort(a + 1, a + 1 + n, z);
FL(i, 1, n - 1)a[n + i] = LCA(a[i], a[i + 1]);
int len = (sort(a + 1, a + n * 2, z), unique(a + 1, a + n * 2)) - a - 1;
FL(i, 1, len - 1)e1[(LCA(a[i + 1], a[i]))].eb(a[i + 1]);
}
那么这题直接对每个询问建虚树,然后简单树形 DP 即可。
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define FL(a,b,c) for(int a=(b),a##end=(c);a<=a##end;++a)
#define FR(a,b,c) for(int a=(b),a##end=(c);a>=a##end;--a)
#define lowbit(x) ((x)&-(x))
#define eb emplace_back
#define SZ(x) (int)((x).size())
#define int long long
#define vt vector
#define fr first
#define se second
#define ar(x) array<int,x>
#define PII pair<int, int>
#define max(a, b)({auto f7r=(a);auto j3h=(b);f7r<j3h?j3h:f7r;})
#define cmax(a, b)({auto j3h=(b);(j3h>a)&&(a=j3h);})
#define min(a, b)({auto f7r=(a);auto j3h=(b);f7r>j3h?j3h:f7r;})
#define cmin(a, b)({auto j3h=(b);(j3h<a)&&(a=j3h);})
constexpr int N = 1e6 + 10;
int n, m, mi[N], lb[N], dep[N], fa[N], a[N], dfn[N], tot, d[N], vis[N];
vt<PII>e[N];
vt<int>e1[N];
void dfs(int x, int f){
int w = lb[f], y = lb[w];
dep[x] = dep[fa[x] = f] + 1, dfn[x] = ++tot;
lb[x] = (dep[y] + dep[f] == dep[w] * 2) ? y : f;
for(PII v : e[x])if(v.fr != f)mi[v.fr] = min(mi[x], v.se), dfs(v.fr, x);
}
int LCA(int x, int y){
if(dep[x] < dep[y])swap(x, y);
while(dep[x] > dep[y])x = x[dep[lb[x]] >= dep[y] ? lb : fa];
while(x != y)
if(lb[x] != lb[y])x = lb[x], y = lb[y];
else x = fa[x], y = fa[y];
return x;
}
int dfs(int x){
int sum = 0;
for(int v : e1[x])sum += dfs(v);
vis[x] ? sum = mi[x] : cmin(sum, mi[x]);
return vis[x] = 0, e1[x].clear(), sum;
}
void build(int n){
auto z = [&](int&i, int&j){return dfn[i] < dfn[j];};
a[++n] = 1, sort(a + 1, a + 1 + n, z);
FL(i, 1, n - 1)a[n + i] = LCA(a[i], a[i + 1]);
int len = (sort(a + 1, a + n * 2, z), unique(a + 1, a + n * 2)) - a - 1;
FL(i, 1, len - 1)e1[(LCA(a[i + 1], a[i]))].eb(a[i + 1]);
}
int32_t main(){
cin.tie(0)->sync_with_stdio(0);
int u, v, w;
cin >> n;
FL(i, 2, n)cin >> u >> v >> w, e[u].eb(v, w), e[v].eb(u, w);
mi[1] = 1e18, dfs(1, 0);
cin >> m;
while(m--){
cin >> u;
FL(i, 1, u)cin >> a[i], vis[a[i]] = 1;
build(u), cout << dfs(1) << endl;
}
return 0;
}

浙公网安备 33010602011771号