我虚树没很理解啊qwq
就是我们有比较少的询问点,然后我们把不需要考虑的点搞一搞扔掉,然后每次询问给那些询问点单独建一颗树,然后乱搞。
……好吧看来是完全没理解……
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cctype> #define maxn 500000 using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } struct Edge{ int next,to,val; }edge[maxn*2]; int head[maxn],num; inline void add(int from,int to,int val){ edge[++num]=(Edge){head[from],to,val}; head[from]=num; } int stack[maxn],top; int deep[maxn]; int s[maxn][22]; int dfn[maxn],ID; int q[maxn]; long long f[maxn]; long long ans[maxn]; bool flag[maxn]; void dfs(int x,int fa){ deep[x]=deep[fa]+1; dfn[x]=++ID; for(int i=head[x];i;i=edge[i].next){ int to=edge[i].to; if(to==fa) continue; s[to][0]=x; f[to]=min(f[x],(long long)edge[i].val); dfs(to,x); } return; } bool cmp(int a,int b){ return dfn[a]<dfn[b]; } int calclca(int a,int b){ if(deep[a]<deep[b]) swap(a,b); int f=deep[a]-deep[b]; for(int i=0;1<<i<=f;++i) if(f&(1<<i)) a=s[a][i]; if(a==b) return a; for(int i=20;i>=0;--i){ if(s[a][i]==s[b][i]) continue; a=s[a][i];b=s[b][i]; } return s[a][0]; } void calc(int x,int fa){ long long sum=0; ans[x]=f[x]; for(int i=head[x];i;i=edge[i].next){ int to=edge[i].to; if(to==fa) continue; calc(to,x); sum+=ans[to]; } if(sum&&!flag[x]) ans[x]=min(ans[x],sum); head[x]=0; return; } int main(){ f[1]=1e9; f[1]=f[1]*f[1]; int n=read(); for(int i=1;i<n;++i){ int from=read(),to=read(),val=read(); add(from,to,val); add(to,from,val); } dfs(1,1); for(int i=1;i<=20;++i) for(int j=1;j<=n;++j) s[j][i]=s[s[j][i-1]][i-1]; int m=read(); memset(head,0,sizeof(head)); for(int i=1;i<=m;++i){ num=0;top=0; int x=read(); for(int j=1;j<=x;++j){ q[j]=read();flag[q[j]]=1; } sort(q+1,q+x+1,cmp); for(int j=1;j<=x;++j){ if(top==0){ stack[++top]=q[j]; continue; } int lca=calclca(q[j],stack[top]); while(dfn[lca]<dfn[stack[top]]){ if(dfn[lca]>=dfn[stack[top-1]]){ add(lca,stack[top],0); if(stack[--top]!=lca) stack[++top]=lca; break; } add(stack[top-1],stack[top],0); top--; } stack[++top]=q[j]; } while(top>1){ add(stack[top-1],stack[top],0); top--; } calc(stack[1],stack[1]); printf("%lld ",ans[stack[1]]); for(int j=1;j<=x;++j) flag[q[j]]=0; } return 0; }