题解:对询问点建立虚树
然后在虚树上Dp
每个点父边边权为这个点到根的边权最小值
一开始学了假的虚树
一开始竟然没想到父边边权可以这样赋
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=500009;
const int inf=2000000000;
typedef long long Lint;
int n,m,T;
int cntedge;
int head[maxn];
int to[maxn],nex[maxn],dist[maxn];
void Addedge(int x,int y,int z){
// cout<<x<<‘ ‘<<y<<‘ ‘<<z<<endl;
nex[++cntedge]=head[x];
to[cntedge]=y;
dist[cntedge]=z;
head[x]=cntedge;
}
int dfsclock;
int father[maxn],depth[maxn],minedge[maxn];
int L[maxn],R[maxn];
void Dfs(int now,int fa,int ecost){
L[now]=++dfsclock;
father[now]=fa;
depth[now]=depth[fa]+1;
minedge[now]=min(minedge[fa],ecost);
for(int i=head[now];i;i=nex[i]){
if(to[i]==fa)continue;
Dfs(to[i],now,dist[i]);
}
R[now]=++dfsclock;
}
int f[maxn][20];
void LCAinit(){
for(int i=1;i<=n;++i)f[i][0]=father[i];
for(int j=1;j<=19;++j){
for(int i=1;i<=n;++i){
f[i][j]=f[f[i][j-1]][j-1];
}
}
}
int Getlca(int u,int v){
if(depth[u]<depth[v])swap(u,v);
for(int j=19;j>=0;--j){
if(depth[f[u][j]]>=depth[v])u=f[u][j];
}
if(u==v)return u;
for(int j=19;j>=0;--j){
if(f[u][j]!=f[v][j]){
u=f[u][j];v=f[v][j];
}
}
return f[u][0];
}
int h[maxn];
int ene[maxn];
int cmp(const int &rhs1,const int &rhs2){
return L[rhs1]<L[rhs2];
}
int S[maxn],top;
inline int intree(int x,int y){
return (L[x]>=L[y])&&(R[x]<=R[y]);
}
Lint g[maxn];
int q[maxn];
void Dp(int x,int fa){
if(ene[x]){
q[x]=1;g[x]=inf;return;
}
q[x]=g[x]=0;
for(int i=head[x];i;i=nex[i]){
if(to[i]==fa)continue;
Dp(to[i],x);
q[x]|=q[to[i]];
if(q[to[i]])g[x]+=min(g[to[i]],dist[i]*1LL);
}
}
int Xsize;
int a[maxn];
int main(){
scanf("%d",&n);
for(int i=1;i<=n-1;++i){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
Addedge(x,y,z);
Addedge(y,x,z);
}
minedge[0]=inf;
Dfs(1,0,inf);
LCAinit();
memset(head,0,sizeof(head));
scanf("%d",&T);
while(T--){
// cout<<"begin"<<endl;
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",&h[i]);ene[h[i]]=1;
}
sort(h+1,h+1+n,cmp);
// for(int i=1;i<=n;++i)cout<<h[i]<<‘ ‘;
// cout<<endl;
cntedge=Xsize=0;
S[top=1]=1;a[++Xsize]=1;
for(int i=1;i<=n;++i){
int lca=Getlca(h[i],S[top]);
while(!intree(h[i],S[top])){
if(intree(lca,S[top-1])){
Addedge(lca,S[top],minedge[S[top]]);--top;break;
}
Addedge(S[top-1],S[top],minedge[S[top]]);--top;
}
if(S[top]!=lca){
S[++top]=lca;a[++Xsize]=lca;
}
S[++top]=h[i];a[++Xsize]=h[i];
}
while(top>1){
Addedge(S[top-1],S[top],minedge[S[top]]);--top;
}
Dp(1,0);
printf("%lld\n",g[1]);
for(int i=1;i<=Xsize;++i){
ene[a[i]]=head[a[i]]=0;
}
}
return 0;
}