继续水虚树。
这题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; }