好长啊题目。。。
大概就是把一棵树分成两棵再拼成一棵后的最大最小直径。应该可以想到树形DP,保存每个节点为根的子树的直径和除去该子树后的直径。为此我们需要维护每个节点向下的前三长的链(每个儿子只记一次),向上最长的链,儿子中前二长的直径,然后可以求出在哪里断开。最后把两棵树的直径找粗来,并起来即可。
说起来好像很简单,然而我做了一周。。真是太弱了。。。
代码比较丑2333
#include
#include
#include
#include
#define N 500005
using namespace std;
int n,x,y;
int first[N],to[N<<1],next[N<<1],l;
int fa[N],dep[N],Max[N],Min[N],dis[N],X,ba[N];
int dia[N],cha[N][4],Mx[N][3],dia1[N],cha1[N];
void link(int x,int y)
{
to[++l]=y;next[l]=first[x];first[x]=l;
to[++l]=x;next[l]=first[y];first[y]=l;
}
void dfs(int x)
{
dep[x]=dep[fa[x]]+1;
for (int i=first[x];i;i=next[i])
if (to[i]!=fa[x])
{
fa[to[i]]=x;
dfs(to[i]);
int t;
int k=cha[to[i]][0]+1;
for (t=3;t&&cha[x][t-1]dis[X]) X=x;
for (int i=first[x];i;i=next[i])
if (to[i]!=ba[x]&&to[i]!=y)
{
ba[to[i]]=x;
Dfs(to[i],y);
}
}
int Getfar(int x,int y)
{
memset(dis,-1,sizeof dis);
memset(ba,0,sizeof ba);
dis[x]=0;X=x;Dfs(x,y);
return X;
}
int Getmid(int x,int y,int l)
{
l/=2;
if (dep[x]Min[i]) Ans2=i;
}
if (Ans2==1) printf("%d %d %d %d %d\n",Min[1],x,y,x,y);
else
{
printf("%d %d %d ",Min[Ans2],Ans2,fa[Ans2]);
int t1=Getfar(Ans2,fa[Ans2]),t2=Getfar(t1,fa[Ans2]),tt1=Getfar(fa[Ans2],Ans2),tt2=Getfar(tt1,Ans2);
printf("%d %d\n",Getmid(t1,t2,dia[Ans2]),Getmid(tt1,tt2,dia1[Ans2]));
}
if (Ans1==1) printf("%d %d %d %d %d\n",Max[1],x,y,x,y);
else
{
printf("%d %d %d ",Max[Ans1],Ans1,fa[Ans1]);
printf("%d %d\n",Getfar(Ans1,fa[Ans1]),Getfar(fa[Ans1],Ans1));
}
}
自己的"SPJ"
#include
#include
#include
#define N 2000005
using namespace std;
int n,Ans,x,y,xx,yy,t,X;
int first[N],next[N],to[N],f[N],fa[N],dis[N],l;
void link(int x,int y)
{
to[++l]=y;next[l]=first[x];first[x]=l;
to[++l]=x;next[l]=first[y];first[y]=l;
}
void dfs(int x)
{
dis[x]=dis[fa[x]]+1;
if (dis[x]>dis[X]) X=x;
for (int i=first[x];i;i=next[i])
if (!f[i]&&to[i]!=fa[x])
{
fa[to[i]]=x;
dfs(to[i]);
}
}
int Get()
{
memset(dis,-1,sizeof dis);
memset(fa,0,sizeof fa);
dis[1]=0;X=1;dfs(1);
memset(dis,-1,sizeof dis);
memset(fa,0,sizeof fa);
dis[X]=0;dfs(X);
return dis[X];
}
int main()
{
freopen("1.in","r",stdin);
scanf("%d",&n);
for (int i=1;i