题目大意,切掉若干条边,使根不能到指定的点,代价最小,多次询问。
这篇东西不错:点击打开链接
虚树的模板题,注意卡时,在建虚树前先将一条链的点删剩一个,每个点记录到根最短的边边权。
貌似数据有误?反正我开了long long 记录边权就A了。
LCA模板一定不能错啊啊啊啊!
code:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const LL inf=(1LL<<56);
struct trnode{
int dep,fa[25];
}tr[250010];int ys[250010],z=0;LL C[250010];
LL f[250010];
struct node{
int y,next;
LL c;
}a[500010];int last[250010],len;
int n,h[250010],num;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int LLread()
{
LL x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void ins(int x,int y,LL c)
{
a[++len].y=y;a[len].c=c;
a[len].next=last[x];last[x]=len;
}
void dfs(int x,int fa,LL c)
{
ys[x]=++z;tr[x].fa[0]=fa;tr[x].dep=tr[fa].dep+1;C[x]=c;
for(int i=1;(1<<i)<=tr[x].dep;i++)
tr[x].fa[i]=tr[tr[x].fa[i-1]].fa[i-1];
for(int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if(y!=fa) dfs(y,x,min(a[i].c,c));
}
}
int findlca(int x,int y)
{
if(tr[x].dep<tr[y].dep) swap(x,y);
for(int i=19;i>=0;i--)
if((1<<i)<=tr[x].dep-tr[y].dep) x=tr[x].fa[i];
if(x==y) return x;
for(int i=19;i>=0;i--)
if((1<<i)<=tr[x].dep&&tr[x].fa[i]!=tr[y].fa[i])
x=tr[x].fa[i],y=tr[y].fa[i];
return tr[x].fa[0];
}
bool cmp(int a,int b){return ys[a]<ys[b];}
int sta[250010],top;
void dfs(int x)
{
f[x]=(LL)C[x];
LL s=0;
for(int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
dfs(y);s+=f[y];
}
if(last[x]) f[x]=min(f[x],s);
last[x]=0;
}
void build()
{
top=0;sort(h+1,h+num+1,cmp);
sta[++top]=1;int tot=num;num=1;
for(int i=2;i<=tot;i++)
{
int lca=findlca(h[num],h[i]);
if(lca!=h[num]) h[++num]=h[i];
}
len=0;
for(int i=1;i<=num;i++)
{
int x=h[i],lca=findlca(sta[top],x);
if(lca==sta[top]) sta[++top]=x;
else
{
while(top>=2&&tr[sta[top-1]].dep>=tr[lca].dep)
{
ins(sta[top-1],sta[top],1LL);
top--;
}
if(lca!=sta[top])
{
ins(lca,sta[top],1LL);
sta[top]=lca;
}
sta[++top]=x;
}
}
for(int i=1;i<top;i++) ins(sta[i],sta[i+1],1);
dfs(1);
printf("%lld\n",f[1]);
}
int main()
{
n=read();
memset(last,0,sizeof(last));len=0;
for(int i=1;i<n;i++)
{
int x,y,c;x=read();y=read();c=LLread();
ins(x,y,c);ins(y,x,c);
}
tr[0].dep=-1;dfs(1,0,inf);
int T;T=read();
memset(last,0,sizeof(last));
while(T--)
{
num=read();
for(int i=1;i<=num;i++) h[i]=read();
build();
}
}