首先肯定建出虚树
考虑三种答案如何分别统计
路径长度和显然示是对于每条边考虑一下上下有多少个点,乘一下就可以了
最大值显然就是树的直径
最小值可以考虑树形,考虑表示到其子树中最近的距离
显然可以类似直径树形解决
#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline int read(){
char ch=getchar();
int res=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
return res*f;
}
const int N=1000005;
const ll inf=1e9;
namespace T{
int adj[N],nxt[N<<1],to[N<<1],cnt,siz[N],dfn[N],tot,son[N],top[N],fa[N],dep[N];
inline void addedge(int u,int v){
nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v;
}
void dfs1(int u){
siz[u]=1;
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(v==fa[u])continue;
fa[v]=u,dep[v]=dep[u]+1;
dfs1(v),siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs2(int u,int tp){
dfn[u]=++tot,top[u]=tp;
if(son[u])dfs2(son[u],tp);
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
}
inline int Lca(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
u=fa[top[u]];
}
return dep[u]>dep[v]?v:u;
}
};
int n,adj[N],nxt[N<<1],to[N<<1],cnt,q,a[N],stk[N],top,k,vis[N],siz[N],ans2,ans3,mx[N],mn[N];
ll ans1;
inline void addedge(int u,int v){
nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v;
}
inline bool comp(const int &a,const int &b){
return T::dfn[a]<T::dfn[b];
}
inline void chemn(int &a,int b){
a=a>b?b:a;
}
inline void chemx(int &a,int b){
a=a>b?a:b;
}
void dp(int u){
mx[u]=0,mn[u]=inf,siz[u]=vis[u];
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
int d=T::dep[v]-T::dep[u];
dp(v),siz[u]+=siz[v];
ans1+=1ll*siz[v]*(k-siz[v])*d;
chemn(ans2,mn[u]+mn[v]+d),chemn(mn[u],mn[v]+d);
chemx(ans3,mx[u]+mx[v]+d),chemx(mx[u],mx[v]+d);
}
if(vis[u])chemn(ans2,mn[u]),chemx(ans3,mx[u]),mn[u]=0;
adj[u]=0;
}
inline void work(){
top=0,cnt=0;
for(int i=1;i<=k;i++){
if(!top){stk[++top]=a[i];continue;}
int lca=T::Lca(stk[top],a[i]);
while(T::dfn[lca]<T::dfn[stk[top]]){
if(T::dfn[lca]>=T::dfn[stk[top-1]]){
addedge(lca,stk[top]);
if(stk[--top]!=lca)stk[++top]=lca;
break;
}
addedge(stk[top-1],stk[top]),top--;
}
stk[++top]=a[i];
}
while(top>1)addedge(stk[top-1],stk[top]),top--;
ans1=0,ans2=inf,ans3=0,dp(stk[1]);
for(int i=1;i<=k;i++)vis[a[i]]=0;
cout<<ans1<<" "<<ans2<<" "<<ans3<<'
';
}
int main(){
n=read();
for(int i=1;i<n;i++){
int u=read(),v=read();
T::addedge(u,v),T::addedge(v,u);
}
T::dfs1(1),T::dfs2(1,1);
q=read();
for(int i=1;i<=q;i++){
k=read();
for(int j=1;j<=k;j++)a[j]=read(),vis[a[j]]=1;
sort(a+1,a+k+1,comp),work();
}
}