题意:给你一棵树求两个点使得树上所有点到这两个点路径长度的最小值最小
取直径的中点拆掉拆成两棵树,分别求两边的直径中点就是答案==QAQ细节真多==还会爆栈不开心
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(j,k,l) for (int j=k;j<=l;j++)
#define N 400005
using namespace std;
int T,n,cnt,lft,rgt,to[N*2],ne[N*2],st[N],deep[N],miaom[3];
int used[N],last[N],que[N];
void add(int k,int l){
to[++cnt]=l;
ne[cnt]=st[k];
st[k]=cnt;
}
int bfs(int k){
int head=0,tail=1,_=k;
memset(used,0,sizeof(used));
used[k]=1;que[1]=k;deep[k]=1;last[k]=0;
while (head<tail){
int x=que[++head];
for (int i=st[x];i;i=ne[i])
if (used[to[i]]==0&&(!((x==lft||x==rgt)&&(x+to[i]==lft+rgt)))){
que[++tail]=to[i];
deep[to[i]]=deep[x]+1;
if (deep[to[i]]>deep[_]) _=to[i];
used[to[i]]=1;
last[to[i]]=x;
}
}
return _;
}
void init(){
cnt=0;
scanf("%d",&n);
rep(i,1,n) st[i]=0;
rep(i,1,n-1){
int k,l;
scanf("%d%d",&k,&l);
add(k,l);add(l,k);
}
}
int mddl(int k,int poi){
int o=bfs(k);
int p=bfs(o);
miaom[poi]=deep[p]/2;
for (int i=p;i;i=last[i])
if (deep[i]==deep[p]+1-(deep[p]+1)/2) return i;
}
void solve(){
lft=0;rgt=0;
rgt=mddl(1,0);lft=last[rgt];
int k=mddl(lft,1),l=mddl(rgt,2);
lft=0;rgt=0;
n=bfs(1);
printf("%d %d %d\n",max(miaom[2],max(miaom[1],abs(deep[k]-deep[l])/2)),k,l);
}
int main(){
scanf("%d",&T);
while (T--){
init();
solve();
}
}