题意:给一颗节点数>=2的树,在树上标记两个点,使得所有点到离它最近的点的最大距离最小。

这题需要了解树的直径以及树的中心这两个概念
树的中心是树上所有点到这个点的最大距离最小
树的直径是树的最长链
我的做法是,先找到树的中心,如果中心有两个(树的中心一定不会大于2个),就劈成两个子树,求两个子树的中心
如果树的中心有一个,就劈开直径上一条边,拆成两颗子树,求这两棵子树的中心。
代码复用性比较挫。。一份个代码写了6遍。。
代码:

//author: CHC
//First Edit Time: 2015-08-15 09:45
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <algorithm>
#include <limits>
using namespace std;
typedef long long LL;
const int MAXN=200000+1000;
const int INF = numeric_limits<int>::max();
const LL LL_INF= numeric_limits<LL>::max();
struct Edge {
int to,next;
Edge(){}
Edge(int _to,int _next):to(_to),next(_next){}
}e[MAXN*2];
int head[MAXN],tot;
void init(){
memset(head,-1,sizeof(head));
tot=0;
}
void AddEdge(int u,int v){
e[tot]=Edge(v,head[u]);
head[u]=tot++;
e[tot]=Edge(u,head[v]);
head[v]=tot++;
}
int dis[MAXN],vis[MAXN],pre[MAXN],du[MAXN];
int mainpath[MAXN];
void bfs(int x,int flag,int y){
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis));
memset(du,0,sizeof(du));
queue <int> q;
q.push(x);
vis[x]=1;
dis[x]=1;
pre[x]=x;
while(!q.empty()){
int now=q.front();
q.pop();
for(int i=head[now];~i;i=e[i].next){
int next=e[i].to;
if(flag&&next==y)continue;
if(vis[next])continue;
du[now]++;du[next]++;
vis[next]=1;
dis[next]=dis[now]+1;
pre[next]=now;
q.push(next);
}
}
}
int vis2[MAXN];
void bfs1(int x){
memset(vis2,0,sizeof(vis2));
memset(dis,0,sizeof(dis));
dis[x]=1;
queue <int> q;
q.push(x);
vis2[x]=1;
pre[x]=x;
while(!q.empty()){
int now=q.front();
q.pop();
for(int i=head[now];~i;i=e[i].next){
int next=e[i].to;
if(vis[next]&&!vis2[next]){
//printf("%d --> %d\n",now,next);
vis2[next]=1;
dis[next]=dis[now]+1;
pre[next]=now;
q.push(next);
}
}
}
}
int hpath[MAXN];
void getmainpath(int x){
memset(hpath,0,sizeof(hpath));
mainpath[0]=0;
while(pre[x]!=x){
mainpath[++mainpath[0]]=x;
hpath[x]=1;
//printf("x:%d\n",x);
x=pre[x];
}
//printf("x:%d\n",x);
mainpath[++mainpath[0]]=x;
hpath[x]=1;
}
int main()
{
int T,n;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
init();
for(int i=0,x,y;i<n-1;i++){
scanf("%d%d",&x,&y);
AddEdge(x,y);
}
/*
if(n==2){
puts("0 1 2");
continue;
}
else if(n==3){
puts("1 1 2");
continue;
}
*/
int maxdis=0,maxu;
bfs(1,0,0);
int tu=1;
for(int i=1;i<=n;i++){
if(du[i]==1){
tu=i;break;
}
}
bfs1(tu);
maxdis=0;
for(int i=1;i<=n;i++){
if(maxdis<dis[i]){
maxu=i;maxdis=dis[i];
}
}
//printf("maxdis%d %d\n",maxdis,maxu);
bfs1(maxu);
maxdis=0;
for(int i=1;i<=n;i++){
if(maxdis<dis[i]){
maxu=i;maxdis=dis[i];
}
}

getmainpath(maxu);
int ans1,ans2;
int dis1,dis2;
//printf("maxdis%d %d\n",maxdis,maxu);
//system("pause");
if(maxdis%2==0){
int mid=maxdis/2;
int midl=mid;
int midr=midl+1;
int midu,midv;
//printf("midlr:%d %d %d\n",mid,midl,midr);
for(int i=1;i<=mainpath[0];i++){
//printf("%d:%d ",mainpath[i],dis[mainpath[i]]);
if(dis[mainpath[i]]==midl){
midu=mainpath[i];
}
if(dis[mainpath[i]]==midr){
midv=mainpath[i];
}
}
//printf("miduv:%d %d\n",midu,midv);
while(midu==midv);
bfs(midu,1,midv);
int tu=midu;
for(int i=1;i<=n;i++){
if(vis[i]&&du[i]==1){
tu=i;break;
}
}
bfs1(tu);
maxdis=0;
for(int i=1;i<=n;i++){
if(dis[i]>maxdis){
maxdis=dis[i];maxu=i;
}
}
bfs1(maxu);
maxdis=0;
for(int i=1;i<=n;i++){
if(dis[i]>maxdis){
maxdis=dis[i];maxu=i;
}
}
getmainpath(maxu);
for(int i=1;i<=mainpath[0];i++){
if(dis[mainpath[i]]==maxdis/2+1){
ans1=mainpath[i];
}
}
dis1=maxdis/2;
//printf("ans1:%d\n",ans1);

bfs(midv,1,midu);
tu=midv;
for(int i=1;i<=n;i++){
if(vis[i]&&du[i]==1){
tu=i;break;
}
}
bfs1(tu);
maxdis=0;
for(int i=1;i<=n;i++){
if(dis[i]>maxdis){
maxdis=dis[i];maxu=i;
}
}
bfs1(maxu);
maxdis=0;
for(int i=1;i<=n;i++){
if(dis[i]>maxdis){
maxdis=dis[i];maxu=i;
}
}
getmainpath(maxu);
for(int i=1;i<=mainpath[0];i++){
if(dis[mainpath[i]]==maxdis/2+1){
ans2=mainpath[i];
}
}
dis2=maxdis/2;
printf("%d %d %d\n",max(dis1,dis2),ans1,ans2);
}
else {
int mid=maxdis/2+1;
int midu,midv;
//printf("mid:%d\n",mid);
for(int i=1;i<=mainpath[0];i++){
if(dis[mainpath[i]]==mid){
midu=mainpath[i];
}
}
//printf("midu:%d\n",midu);
midv=midu;
for(int i=head[midu];~i;i=e[i].next){
if(hpath[e[i].to]){
midv=e[i].to;break;
}
}
while(midu==midv);
//printf("midu:%d midv:%d\n",midu,midv);
bfs(midu,1,midv);
int tu=midu;
for(int i=1;i<=n;i++){
if(vis[i]&&du[i]==1){
tu=i;break;
}
}
//printf("tu:%d\n",tu);
bfs1(tu);
maxdis=0;
for(int i=1;i<=n;i++){
if(maxdis<dis[i]){
maxdis=dis[i];
maxu=i;
}
}
bfs1(maxu);
maxdis=0;
for(int i=1;i<=n;i++){
if(maxdis<dis[i]){
maxdis=dis[i];
maxu=i;
}
}
getmainpath(maxu);
//printf("maxu:%d %d\n",maxu,maxdis/2+1);
for(int i=1;i<=mainpath[0];i++){
//printf("%d:%d ",i,dis[i]);
if(dis[mainpath[i]]==maxdis/2+1){
//printf("here:%d\n",i);
ans1=mainpath[i];
}
}
//puts("");
//printf("ans1:%d\n",ans1);
dis1=maxdis/2;

bfs(midv,1,midu);
tu=midv;
for(int i=1;i<=n;i++){
if(vis[i]&&du[i]==1){
tu=i;break;
}
}
//printf("tu:%d\n",tu);
bfs1(tu);
maxdis=0;
for(int i=1;i<=n;i++){
if(maxdis<dis[i]){
maxdis=dis[i];
maxu=i;
}
}
bfs1(maxu);
maxdis=0;
for(int i=1;i<=n;i++){
if(maxdis<dis[i]){
maxdis=dis[i];
maxu=i;
}
}
getmainpath(maxu);
//printf("maxu:%d\n",maxu);
for(int i=1;i<=mainpath[0];i++){
if(dis[mainpath[i]]==maxdis/2+1){
ans2=mainpath[i];
}
}
dis2=maxdis/2;
printf("%d %d %d\n",max(dis1,dis2),ans1,ans2);
}
}
return 0;
}
/*
8
1 2
1 3
1 4
2 7
2 8
3 5
5 6

10
1 2
2 3
3 10
1 4
4 5
1 8
8 9
1 6
6 7

13
1 2
2 3
3 10
1 4
4 5
1 8
8 9
1 6
6 7
10 11
11 12
12 13

11
1 2
2 3
3 4
4 5
5 6
6 7
7 8
6 9
9 10
10 11
*/