bzoj2286:[SDOI2011]消耗战
传送门
虚树裸题,建完虚树上tree dp就好了
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
void read(int &x) {
char ch; bool ok;
for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
const int maxn=2.5e5+10;
int f[maxn][20],nid,dep[maxn],top,st[maxn],n,m,id[maxn],q[maxn];
struct oo{int cnt,pre[maxn*2],nxt[maxn*2],h[maxn],v[maxn*2];}a,b;
long long w[maxn],ans[maxn];
void add(int x,int y,int z)
{
a.pre[++a.cnt]=y,a.nxt[a.cnt]=a.h[x],a.h[x]=a.cnt,a.v[a.cnt]=z;
a.pre[++a.cnt]=x,a.nxt[a.cnt]=a.h[y],a.h[y]=a.cnt,a.v[a.cnt]=z;
}
void dfs(int x,int fa)
{
for(rg int i=1;i<20;i++)
{
if((1<<i)>dep[x])break;
f[x][i]=f[f[x][i-1]][i-1];
}
id[x]=++nid;
for(rg int i=a.h[x];i;i=a.nxt[i])
if(a.pre[i]!=fa)
{
f[a.pre[i]][0]=x,dep[a.pre[i]]=dep[x]+1;
w[a.pre[i]]=min(w[x],1ll*a.v[i]),dfs(a.pre[i],x);
}
}
int lca(int x,int y)
{
if(dep[x]>dep[y])swap(x,y);
int poor=dep[y]-dep[x];
for(rg int i=19;i>=0;i--)if(poor&(1<<i))y=f[y][i];
for(rg int i=19;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
return x==y?x:f[x][0];
}
bool cmp(int x,int y){return id[x]<id[y];}
void link(int x,int y)
{
b.pre[++b.cnt]=y,b.nxt[b.cnt]=b.h[x],b.h[x]=b.cnt;
b.pre[++b.cnt]=x,b.nxt[b.cnt]=b.h[y],b.h[y]=b.cnt;
}
void dp(int x,int fa)
{
long long now=0;ans[x]=w[x];
for(rg int i=b.h[x];i;i=b.nxt[i])if(b.pre[i]!=fa)dp(b.pre[i],x),now+=ans[b.pre[i]];
b.h[x]=0;
if(now)ans[x]=min(ans[x],now);
// printf("%d %d %d\n",x,ans[x],w[x]);
}
signed main()
{
read(n);
for(rg int i=1,x,y,z;i<n;i++)read(x),read(y),read(z),add(x,y,z);
w[1]=1e17,dfs(1,0),read(m);
for(rg int x=1,t;x<=m;x++)
{
read(t),b.cnt=top=0;
for(rg int i=1;i<=t;i++)read(q[i]);
sort(q+1,q+t+1,cmp);st[++top]=1;int tot=1;
for(rg int i=2;i<=t;i++)if(lca(q[i],q[tot])!=q[tot])q[++tot]=q[i];
for(rg int i=1;i<=tot;i++)
{
int w=0,e=0;
while(top&&lca(st[top],q[i])!=st[top])
{
if(w)link(w,st[top]);
w=st[top],top--;
}
if(w)e=lca(w,q[i]),link(w,e);
if(e&&e!=st[top])st[++top]=e;
st[++top]=q[i];
}
while(top>1)link(st[top],st[top-1]),top--;
dp(1,0);
printf("%lld\n",ans[1]);
}
}