分析
这道题目需要建立虚树,也就是建一棵所需点与它们lca组成的树,在树上dp,由于题目比较经典,就直接贴代码了
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
#include <cstring>
#define rr register
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const int N=250101; ll minx[N];
struct node{int y,next;}e[N<<1],E[N];
int fat[N],dep[N],ls[N],hs[N],w[N<<1],son[N],n;
int big[N],top[N],stac[N],k=1,K,dfn[N],a[N],tot;
inline signed iut(){
rr int ans=0,f=1; rr char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans*f;
}
inline void print(ll ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline void add(int x,int y){E[++K]=(node){y,hs[x]},hs[x]=K;}
inline void dfs1(int x,int fa){
dep[x]=dep[fa]+1,fat[x]=fa,son[x]=1;
for (rr int i=ls[x],mson=-1;i;i=e[i].next)
if (e[i].y!=fa){
minx[e[i].y]=min(minx[x],w[i]);//维护根节点到该点的最小边权
dfs1(e[i].y,x);
son[x]+=son[e[i].y];
if (son[e[i].y]>mson)
big[x]=e[i].y,mson=son[e[i].y];
}
}
inline void dfs2(int x,int linp){
dfn[x]=++tot,top[x]=linp;
if (!big[x]) return; dfs2(big[x],linp);
for (rr int i=ls[x];i;i=e[i].next)
if (e[i].y!=fat[x]&&e[i].y!=big[x]) dfs2(e[i].y,e[i].y);
}
inline signed lca(int x,int y){
while (top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) x^=y,y^=x,x^=y;
x=fat[top[x]];
}
if (dep[x]>dep[y]) x^=y,y^=x,x^=y;
return x;
}
inline bool cmp(int x,int y){return dfn[x]<dfn[y];}
inline ll dfs(int x){
if (!hs[x]) return minx[x];
rr ll ans=0;
for (rr int i=hs[x];i;i=E[i].next)
ans+=dfs(E[i].y);
hs[x]=0;
return min(ans,minx[x]);
}
inline void Insert(int x){
if (tot==1) {stac[++tot]=x; return;}//只有一个点直接建
rr int Lca=lca(x,stac[tot]);
if (Lca==stac[tot]) return;//不需要建边
while (tot>1&&dfn[stac[tot-1]]>=dfn[Lca]) add(stac[tot-1],stac[tot]),--tot;//单调栈
if (Lca!=stac[tot]) add(Lca,stac[tot]),stac[tot]=Lca; stac[++tot]=x;//加入该点
}
signed main(){
n=iut();
memset(minx,42,sizeof(minx));
for (rr int i=1;i<n;++i){
rr int x=iut(),y=iut(),z=iut();
e[++k]=(node){y,ls[x]},ls[x]=k,
e[++k]=(node){x,ls[y]},ls[y]=k,
w[k]=w[k^1]=z;
}
dfs1(1,0),dfs2(1,1),tot=0;
for (rr int m=iut();m;--m){
K=0; rr int q=iut();
for (rr int i=1;i<=q;++i) a[i]=iut();
sort(a+1,a+1+q,cmp),stac[tot=1]=1;//按照dfs序排序
for (rr int i=1;i<=q;++i) Insert(a[i]);//依次插入
for (--tot;tot;--tot) add(stac[tot],stac[tot+1]);//建树
print(dfs(1)),putchar(10);
}
return 0;
}