继续水虚树。
这题60S的时限把我吓坏了。
然而3000多MS就A了,有幸到了rank 4,nice!。
一开始还在纠结是点分治还是DP,后来想想既然能DP何不DP呢。
于是就DP了。
显然要维护三个量。
ans2和ans3都好说,参照树上直径的求法就好了,次长+最长+1变形一下。
ans1的话比较麻烦,手画个图看看,目测是当前子树的边与其他子树的边对应,然后其他子树的边再和当前子树的算一下,动手推一推就好了。
然后就OK了。
果然像Clj所说,一开始还很有意思,做多了就审美疲劳了(才一两个好不好)。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int read(){
int x=0;char ch;
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x;
}
const int N=1000000+5;
const int inf=1e9;
struct Edge{int to,next,v;}e[N<<1];
int head[N],cnt;
int siz[N],son[N],dep[N],fa[N],top[N];
int dfn[N],dfs_clock;
void ins(int u,int v){
if(u==v)return;
e[++cnt]=(Edge){v,head[u],dep[v]-dep[u]};head[u]=cnt;
}
void dfs1(int u){
siz[u]=1;son[u]=0;dfn[u]=++dfs_clock;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;if(v==fa[u])continue;
dep[v]=dep[u]+1;fa[v]=u;
dfs1(v);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs2(int u,int tp){
top[u]=tp;
if(son[u])dfs2(son[u],tp);
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v!=son[u]&&v!=fa[u])dfs2(v,v);
}
}
int lca(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]>=dep[top[v]])u=fa[top[u]];
else v=fa[top[v]];
}
return dep[u]<dep[v]?u:v;
}
ll sum[N],ans1;
int mx[N],mi[N],ans2,ans3;
bool build[N];
void dp(int u){
siz[u]=build[u];
mx[u]=build[u]?0:-inf;
mi[u]=build[u]?0:inf;
sum[u]=0;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
dp(v);
ans1+=(sum[u]+siz[u]*e[i].v)*siz[v]+sum[v]*siz[u];
siz[u]+=siz[v];
sum[u]+=sum[v]+siz[v]*e[i].v;
ans2=min(ans2,mi[u]+mi[v]+e[i].v);
ans3=max(ans3,mx[u]+mx[v]+e[i].v);
mi[u]=min(mi[u],mi[v]+e[i].v);
mx[u]=max(mx[u],mx[v]+e[i].v);
}
head[u]=0;
}
int h[N];
int st[N],tp;
bool cmp(int i,int j){
return dfn[i]<dfn[j];
}
void solve(){
int k=read();
for(int i=1;i<=k;i++){
h[i]=read();
build[h[i]]=true;
}
sort(h+1,h+1+k,cmp);
tp=cnt=0;
st[++tp]=1;
for(int i=1;i<=k;i++){
int now=h[i],f=lca(now,st[tp]);
if(f==st[tp]){st[++tp]=now;continue;}
while(f==lca(now,st[tp-1])){
ins(st[tp-1],st[tp]);
tp--;f=lca(now,st[tp]);
}
ins(f,st[tp]);
st[tp]=f;st[++tp]=now;
}
while(--tp)ins(st[tp],st[tp+1]);
ans1=0;ans2=inf;ans3=-inf;
dp(1);
printf("%lld %d %d\n",ans1,ans2,ans3);
for(int i=1;i<=k;i++)build[h[i]]=false;
}
int main(){
int n=read();
int u,v;
for(int i=1;i<n;i++){
u=read();v=read();
ins(u,v);ins(v,u);
}
dfs1(1);dfs2(1,1);
memset(head,0,sizeof(head));
int q=read();
while(q--)solve();
return 0;
}