我太sb了。。一看输出方案就瞎jb记录了一坨信息。。最后发现根本没有用。。
结果写了6.7K。。。成功成为了BZOJ写的最长跑的最慢的选手2333。。
题目即在一棵树上删一边加一边,使得新树的直径最小。
那么我们就要维护直径相关的信息。。于是大力DP。。
首先自底向上DP,设
fi
表示以节点
i
为根的子树的直径,
假设
j,k
为
i
的孩子,且
那么有
gi=max{gj+1}
fi=max{fj,gj+1,gj+gk+2}
然后我们自顶向下DP,类似的,设 hi 表示除去以 i 为根的子树后,剩余树的直径,
设 j,k 是 i 的兄弟,且
那么有
pi=max{pfai+1,gj+2}
hi=max{hfai,pfai+gj+1,fj,gj+gk+2}
然后就记录一些前缀max后缀max最大次大什么的转移就行了。
至于记录方案。。只要把 f,g 相关的转移记录下来就好了,至于 p,h 根本用不到。多写了一坨懒得删了。
然后我们枚举删去某条边
(i,fai)
,那么有
ans=max{fi,hi,⌈fi+12⌉+⌈hi+12⌉+1}
最后 BFS 一下记录方案。
时间复杂度 O(n) 。
附sb代码:
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<queue>
using namespace std;
const int N=300005;
const int inf=1000000007;
int n,cnt,ans,id;
int head[N],list[N<<1],next[N<<1];
int premx[N],sufmx[N],preid[N],sufid[N],fa[N],f[N],g[N],h[N],p[N],q[N];
pair<int,int> pref[N],preh[N];
int preg[N],prep[N],pre[N],path[N];
bool vis[N];
inline int read()
{
int a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}
inline void insert(int x,int y)
{
next[++cnt]=head[x];
head[x]=cnt;
list[cnt]=y;
}
inline int GETANS(int i)
{
return max(max((f[i]+1)/2+(h[i]+1)/2+1,f[i]),h[i]);
}
inline void clear(int tot)
{
for (int i=1;i<=tot+1;i++) sufmx[i]=premx[i]=-inf;
}
void DP1(int x)
{
preg[x]=x,pref[x]=make_pair(x,x);
for (int i=head[x];i;i=next[i])
if (list[i]!=fa[x])
{
fa[list[i]]=x;
DP1(list[i]);
}
int mx1=-inf,mx2=-inf,j1,j2;
for (int i=head[x];i;i=next[i])
if (list[i]!=fa[x])
{
// g[x]=max(g[x],g[list[i]]+1);
if (g[list[i]]+1>g[x]) g[x]=g[list[i]]+1,preg[x]=preg[list[i]];
// f[x]=max(f[x],f[list[i]]);
if (f[list[i]]>f[x]) f[x]=f[list[i]],pref[x]=pref[list[i]];
if (g[list[i]]>mx1) mx2=mx1,mx1=g[list[i]],j2=j1,j1=preg[list[i]];
else if (g[list[i]]>mx2) mx2=g[list[i]],j2=preg[list[i]];
}
// f[x]=max(f[x],g[x]);
if (g[x]>f[x]) f[x]=g[x],pref[x]=make_pair(preg[x],x);
if (mx1!=-inf&&mx2!=-inf)
// f[x]=max(f[x],mx1+mx2+2);
if (mx1+mx2+2>f[x])
f[x]=mx1+mx2+2,pref[x]=make_pair(j1,j2);
}
void DP2(int x)
{
vector<int> q;
q.push_back(0);
for (int i=head[x];i;i=next[i])
if (list[i]!=fa[x]) q.push_back(list[i]);
// cout << x << " : ";
// for (int i=1;i<=tot;i++) cout<< q[i] << " " ;
// cout << endl;
int tot=q.size()-1;
for (int i=1;i<=tot;i++)
{
// h[q[i]]=max(h[q[i]],h[x]);
if (h[x]>h[q[i]]) h[q[i]]=h[x],preh[q[i]]=preh[x];
// p[q[i]]=max(p[q[i]],p[x]+1);
if (p[x]+1>p[q[i]]) p[q[i]]=p[x]+1,prep[q[i]]=prep[x];
}
clear(tot);
for (int i=1;i<=tot;i++)
// premx[i]=max(premx[i-1],f[q[i]]);
if (f[q[i]]>premx[i-1])
premx[i]=f[q[i]],preid[i]=q[i];
else premx[i]=premx[i-1],preid[i]=preid[i-1];
for (int i=tot;i;i--)
// sufmx[i]=max(sufmx[i+1],f[q[i]]);
if (f[q[i]]>sufmx[i+1])
sufmx[i]=f[q[i]],sufid[i]=q[i];
else sufmx[i]=sufmx[i+1],sufid[i]=sufid[i+1];
for (int i=2;i<=tot;i++)
// h[q[i]]=max(h[q[i]],premx[i-1]);
if (premx[i-1]>h[q[i]])
h[q[i]]=premx[i-1],preh[q[i]]=pref[preid[i-1]];
for (int i=1;i<tot;i++)
// h[q[i]]=max(h[q[i]],sufmx[i+1]);
if (sufmx[i+1]>h[q[i]])
h[q[i]]=sufmx[i+1],preh[q[i]]=pref[sufid[i+1]];
clear(tot);
for (int i=1;i<=tot;i++)
// premx[i]=max(premx[i-1],g[q[i]]);
if (g[q[i]]>premx[i-1]) premx[i]=g[q[i]],preid[i]=q[i];
else premx[i]=premx[i-1],preid[i]=preid[i-1];
for (int i=tot;i;i--)
// sufmx[i]=max(sufmx[i+1],g[q[i]]);
if (g[q[i]]>sufmx[i+1]) sufmx[i]=g[q[i]],sufid[i]=q[i];
else sufmx[i]=sufmx[i+1],sufid[i]=sufid[i+1];
for (int i=2;i<=tot;i++)
// p[q[i]]=max(p[q[i]],premx[i-1]+2);
if (premx[i-1]+2>p[q[i]])
p[q[i]]=premx[i-1]+2,prep[q[i]]=preg[preid[i-1]];
for (int i=1;i<tot;i++)
// p[q[i]]=max(p[q[i]],sufmx[i+1]+2);
if (sufmx[i+1]+2>p[q[i]])
p[q[i]]=sufmx[i+1]+2,prep[q[i]]=preg[sufid[i+1]];
if (tot==1)
// h[q[1]]=max(h[q[1]],p[x]);
if (p[x]>h[q[1]])
h[q[1]]=p[x],preh[q[1]]=make_pair(prep[x],x);
for (int i=2;i<=tot;i++)
// h[q[i]]=max(h[q[i]],p[x]+premx[i-1]+1);
if (p[x]+premx[i-1]+1>h[q[i]])
h[q[i]]=p[x]+premx[i-1]+1,preh[q[i]]=make_pair(preg[preid[i-1]],prep[x]);
for (int i=1;i<tot;i++)
// h[q[i]]=max(h[q[i]],p[x]+sufmx[i+1]+1);
if (p[x]+sufmx[i+1]+1>h[q[i]])
h[q[i]]=p[x]+sufmx[i+1]+1,preh[q[i]]=make_pair(preg[sufid[i+1]],prep[x]);
for (int i=2;i<tot;i++)
// h[q[i]]=max(h[q[i]],premx[i-1]+sufmx[i+1]+2);
if (premx[i-1]+sufmx[i+1]+2>h[q[i]])
h[q[i]]=premx[i-1]+sufmx[i+1]+2,preh[q[i]]=make_pair(preg[preid[i-1]],preg[sufid[i+1]]);
int mx1,mx2,j1,j2;
mx1=-inf; mx2=-inf;
for (int i=1;i<=tot;i++)
{
if (mx1!=-inf&&mx2!=-inf)
//h[q[i]]=max(h[q[i]],mx1+mx2+2);
if (mx1+mx2+2>h[q[i]])
h[q[i]]=mx1+mx2+2,preh[q[i]]=make_pair(j1,j2);
if (g[q[i]]>mx1) mx2=mx1,mx1=g[q[i]],j2=j1,j1=preg[q[i]];
else if (g[q[i]]>mx2) mx2=g[q[i]],j2=preg[q[i]];
}
mx1=-inf; mx2=-inf;
for (int i=tot;i;i--)
{
if (mx1!=-inf&&mx2!=-inf)
//h[q[i]]=max(h[q[i]],mx1+mx2+2);
if (mx1+mx2+2>h[q[i]])
h[q[i]]=mx1+mx2+2,preh[q[i]]=make_pair(j1,j2);
if (g[q[i]]>mx1) mx2=mx1,mx1=g[q[i]],j2=j1,j1=preg[q[i]];
else if (g[q[i]]>mx2) mx2=g[q[i]],j2=preg[q[i]];
}
for (int i=1;i<=tot;i++) DP2(q[i]);
}
inline void BFS(int x)
{
memset(vis,0,sizeof(vis));
memset(path,0,sizeof(path));
queue<int> q;
q.push(x); vis[x]=true;
while (!q.empty())
{
int x=q.front(); q.pop();
// cout << x << " ";
for (int i=head[x];i;i=next[i])
if (!vis[list[i]])
{
vis[list[i]]=1;
path[list[i]]=x;
q.push(list[i]);
}
}
}
inline int find(int x,int ff)
{
// cout << "now : " ;
fa[x]=ff; DP1(x);
int st=pref[x].first,en=pref[x].second;
// cout << st << " " << en <<endl;
BFS(st);
// for (int i=1;i<=n;i++) cout << path[i] << " ";
// puts("");
int cnt=0;
int i;
for (i=en;i;i=path[i])
{
// cout << i << " ";
if (++cnt==f[x]/2+1) break;
}
// cout << endl;
return i;
}
int main()
{
// freopen("A1316.out","w",stdout);
n=read();
for (int i=1;i<n;i++)
{
int u=read(),v=read();
insert(u,v); insert(v,u);
}
DP1(1); DP2(1);
// for (int i=1;i<=n;i++) cout << p[i] <<" ";
// cout << endl;
ans=inf;
for (int i=1;i<=n;i++)
// ans=min(ans,max(max((f[i]+1)/2+(h[i]+1)/2+1,f[i]),h[i]));
if (GETANS(i)<ans) ans=GETANS(i),id=i;
int A=id,B=fa[id];
memset(fa,0,sizeof(fa));
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
printf("%d\n%d %d\n%d %d\n",ans,A,B,find(A,B),find(B,A));
// for (int i=1;i<=n;i++)
// cout << i << " " << fa[i] << endl;
return 0;
}