【题解】P2495 【模板】虚树 / [SDOI2011] 消耗战
【P2495】题解
一:【题意】
- 给定一张带边权图
- 每次给出关键点,求切断所有关键点与1联系的最小花费
二:【解法】
建虚树,预处理每个点到根的边的最小值dis,跑树形dp
dp[u]:切断u子树(不包含u)关键点与1联系的最小花费
枚举u的子节点v
if(v是关键点) dp[u]+=dis[v]
else dp[u]+=min(dis[v],dp[v])
三:【代码】
#include<bits/stdc++.h>
#define Pair pair<int,int>
#define w first
#define to second
#define inf 2e9
using namespace std;
typedef long long LL;
const int N=2.5e5+10;
vector<Pair> mp[N];
int siz[N];
int fa[N];
int dep[N];
int son[N];
void Son(int u,int pa){
siz[u]=1;
dep[u]=dep[pa]+1;
fa[u]=pa;
for(auto e:mp[u]){
int v=e.to;
if(v==pa) continue;
Son(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
int top[N],dfn[N],cnt;
void Line(int u,int tp){
dfn[u]=++cnt;
top[u]=tp;
if(!son[u]) return ;
Line(son[u],tp);
for(auto e:mp[u]){
int v=e.to;
if(v==fa[u]||v==son[u]) continue;
Line(v,v);
}
}
int LCA(int a,int b){
while(top[a]!=top[b]){
if(dep[top[a]]<dep[top[b]]) swap(a,b);
a=fa[top[a]];
}
if(dep[a]>dep[b]) swap(a,b);
return a;
}
LL dis[N];
void Min(int u,int fa){
for(auto e:mp[u]){
int v=e.to,w=e.w;
if(v==fa) continue;
dis[v]=min(dis[u],(LL)w);
Min(v,u);
}
}
int im[N];
vector<int> st;
bool cmp(int x,int y){
return dfn[x]<dfn[y];
}
vector<int> tmp[N];
void Build(){
sort(st.begin(),st.end(),cmp);
int len=st.size();
for(int i=0;i<len-1;i++) st.push_back(LCA(st[i],st[i+1]));
sort(st.begin(),st.end(),cmp);
st.erase(unique(st.begin(),st.end()),st.end());
for(int i=0;i<st.size()-1;i++) tmp[LCA(st[i],st[i+1])].push_back(st[i+1]);
}
LL Dp(int u,int fa){
LL sum=0;
for(auto v:tmp[u]){
if(v==fa) continue;
if(im[v]) sum+=dis[v];
else sum+=min(dis[v],Dp(v,u));
}
return sum;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int n;cin>>n;
for(int i=1;i<=n;i++) dis[i]=inf;
for(int i=1;i<n;i++){
int a,b,c;cin>>a>>b>>c;
mp[a].push_back({c,b});
mp[b].push_back({c,a});
}
Son(1,1);
Line(1,1);
Min(1,1);
int m;cin>>m;
while(m--){
int len;cin>>len;
for(int i=1;i<=len;i++){
int k;cin>>k;
st.push_back(k);
im[k]=1;
}
st.push_back(1);
Build();
cout<<Dp(1,1)<<"\n";
for(auto u:st){
tmp[u].clear();
im[u]=0;
}
st.clear();
}
return 0;
}

浙公网安备 33010602011771号