https://codeforces.com/problemset/problem/1294/F
对于3个点之间的路径并集,我们可以在它的路径并集上找到一个点,使得这个点到这三个点之间的路径互不相交,那么这个问题就转化到了从某个点出发3条不相交的路径最长的问题,那么这就是个经典树形DP了,每个点维护最长路,次长路,次次长路
注意一些细节,最后我们把中心点找出来后,它的每个子树只能找离他最远的一个点,如果没有3个,只有两个子树,那么第3个点任意找一个就行,如果树是一条链,那么只有一个子树,那么答案中要有个点是ansnode本身。
#include<bits/stdc++.h>
using namespace std;
const int maxl=2e5+10;
int n,cnt,tot,ans,ansnode,ans1,ans2,ans3;
int mx,mxnod;
int ehead[maxl],fir[maxl],sec[maxl],thi[maxl];
struct ed
{
int to,nxt;
}e[maxl<<1];
struct node
{
int val,v;
}a[maxl];
inline void add(int u,int v)
{
e[++cnt].to=v;e[cnt].nxt=ehead[u];ehead[u]=cnt;
}
inline void prework()
{
scanf("%d",&n);
int u,v;
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
}
inline void f(int u,int val)
{
if(val>fir[u])
thi[u]=sec[u],sec[u]=fir[u],fir[u]=val;
else if(val>sec[u])
thi[u]=sec[u],sec[u]=val;
else if(val>thi[u])
thi[u]=val;
}
inline void dfs1(int u,int fa)
{
int v;
for(int i=ehead[u];i;i=e[i].nxt)
{
v=e[i].to;
if(v==fa) continue;
dfs1(v,u);
f(u,fir[v]+1);
}
}
inline void dfs2(int u,int fa,int fadis)
{
int v,val;
f(u,fadis);
if(fir[u]+sec[u]+thi[u]>ans)
{
ans=fir[u]+sec[u]+thi[u];
ansnode=u;
}
for(int i=ehead[u];i;i=e[i].nxt)
{
v=e[i].to;
if(v==fa) continue;
if(fir[v]+1==fir[u])
val=max(fadis+1,sec[u]+1);
else
val=max(fadis+1,fir[u]+1);
dfs2(v,u,val);
}
}
inline void dfs(int u,int fa,int dis)
{
if(dis>mx)
{
mx=dis;
mxnod=u;
}
int v;
for(int i=ehead[u];i;i=e[i].nxt)
{
v=e[i].to;
if(v==fa) continue;
dfs(v,u,dis+1);
}
}
inline bool cmp(const node &x,const node &y)
{
return x.val>y.val;
}
inline void mainwork()
{
dfs1(1,0);
dfs2(1,0,0);
int v;
for(int i=ehead[ansnode];i;i=e[i].nxt)
{
v=e[i].to;mx=0;
dfs(v,ansnode,1);
a[++tot]=node{mx,mxnod};
}
sort(a+1,a+1+tot,cmp);
ans1=a[1].v;ans2=a[2].v;ans3=a[3].v;
if(ans2==0) ans2=ansnode;
if(ans3==0) ans3=2;
}
inline void print()
{
printf("%d\n",ans);
printf("%d %d %d",ans1,ans2,ans3);
}
int main()
{
prework();
mainwork();
print();
return 0;
}