两遍树形DP求出每个点开始往上往下走的前3长路以及每个点上下部分的直径。

枚举每条边断开,设两边直径分别为$A,B$,则:

对于第一问,连接两边直径的中点可得直径为$\max(A,B,\lfloor\frac{A+1}{2}\rfloor+\lfloor\frac{B+1}{2}\rfloor+1)$的新树。

对于第二问,连接两边直径的端点可得直径为$A+B+1$的新树。

时间复杂度$O(n)$。

#include<cstdio>
#define N 500010
int n,i,j,x,y,g[N],v[N<<1],nxt[N<<1],del[N<<1],ed,fa[N];
int d[N][3],f[N],w[N][2],u[N],h[N],ans1=N,ans2,ch1,ch2,id,dis[N],pre[N],q[N];
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
inline void up(int&a,int b){if(a<b)a=b;}
inline int max(int a,int b){return a>b?a:b;}
void caldown(int x){
for(int i=g[x];i;i=nxt[i])if(v[i]!=fa[x]){
int y=v[i];
fa[v[i]]=x;
caldown(v[i]);
int t=d[y][0]+1;
if(t>d[x][0])d[x][2]=d[x][1],d[x][1]=d[x][0],d[x][0]=t;
else if(t>d[x][1])d[x][2]=d[x][1],d[x][1]=t;
else if(t>d[x][2])d[x][2]=t;
up(f[x],t=f[y]);
if(t>w[x][0])w[x][1]=w[x][0],w[x][0]=t;else if(t>w[x][1])w[x][1]=t;
}
up(f[x],d[x][0]+d[x][1]);
}
void calup(int x){
if(x!=1){
int y=fa[x];
u[x]=u[y];
up(u[x],d[y][0]==d[x][0]+1?d[y][1]:d[y][0]);
u[x]++;
h[x]=h[y];
up(h[x],w[y][0]==f[x]?w[y][1]:w[y][0]);
int a,b,c=u[y];
if(d[y][0]==d[x][0]+1)a=d[y][1],b=d[y][2];
else a=d[y][0],b=d[y][1]==d[x][0]+1?d[y][2]:d[y][1];
up(h[x],a+b),up(h[x],a+c),up(h[x],b+c);
int t=max(max(h[x],f[x]),(h[x]+1)/2+(f[x]+1)/2+1);
if(t<ans1)ans1=t,ch1=x;
t=h[x]+f[x]+1;
if(t>ans2)ans2=t,ch2=x;
up(h[x],a+1),up(h[x],b+1),up(h[x],c+1);
}
for(int i=g[x];i;i=nxt[i])if(v[i]!=fa[x])calup(v[i]);
}
void dfs(int x,int y){
pre[x]=y;
if(dis[x]>dis[id])id=x;
for(int i=g[x];i;i=nxt[i])if(v[i]!=y&&!del[i])dis[v[i]]=dis[x]+1,dfs(v[i],x);
}
int main(){
read(n);
for(i=1;i<n;i++)read(x),read(y),add(x,y),add(y,x);
caldown(1),calup(1);
printf("%d %d %d",ans1,ch1,fa[ch1]);
for(i=g[ch1];i;i=nxt[i])if(v[i]==fa[ch1])del[i]=1;
for(i=g[fa[ch1]];i;i=nxt[i])if(v[i]==ch1)del[i]=1;
dfs(id=ch1,dis[ch1]=0);
dfs(id,dis[id]=0);
for(i=1;id;i++,id=pre[id])q[i]=id;
printf(" %d",q[i>>1]);
dfs(id=fa[ch1],dis[fa[ch1]]=0);
dfs(id,dis[id]=0);
for(i=1;id;i++,id=pre[id])q[i]=id;
printf(" %d\n",q[i>>1]);
for(i=g[ch1];i;i=nxt[i])if(v[i]==fa[ch1])del[i]=0;
for(i=g[fa[ch1]];i;i=nxt[i])if(v[i]==ch1)del[i]=0;
printf("%d %d %d",ans2,ch2,fa[ch2]);
for(i=g[ch2];i;i=nxt[i])if(v[i]==fa[ch2])del[i]=1;
for(i=g[fa[ch2]];i;i=nxt[i])if(v[i]==ch2)del[i]=1;
dfs(id=ch2,dis[ch2]=0);
printf(" %d",id);
dfs(id=fa[ch2],dis[fa[ch2]]=0);
printf(" %d",id);
return 0;
}

  

BZOJ4379 : [POI2015]Modernizacja autostrady的更多相关文章

  1. [BZOJ4379][POI2015]Modernizacja autostrady[树的直径+换根dp]

    题意 给定一棵 \(n\) 个节点的树,可以断掉一条边再连接任意两个点,询问新构成的树的直径的最小和最大值. \(n\leq 5\times 10^5\) . 分析 记断掉一条边之后两棵树的直径为 \ ...

  2. 【BZOJ4379】[POI2015]Modernizacja autostrady 树形DP

    [BZOJ4379][POI2015]Modernizacja autostrady Description 给定一棵无根树,边权都是1,请去掉一条边并加上一条新边,定义直径为最远的两个点的距离,请输 ...

  3. @bzoj - 4379@ [POI2015] Modernizacja autostrady

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一棵无根树,边权都是1,请去掉一条边并加上一条新边,定义直径 ...

  4. POI2015题解

    POI2015题解 吐槽一下为什么POI2015开始就成了破烂波兰文题目名了啊... 咕了一道3748没写打表题没什么意思,还剩\(BZOJ\)上的\(14\)道题. [BZOJ3746][POI20 ...

  5. [Poi2015]

    [POI2015]Łasuchy 一看以为是sb题 简单来说就是每个人获得热量要尽量多 不能找别人 首先这道题好像我自己找不到NIE的情况 很容易想到一个优化 如果一个数/2>另一个数 那么一定 ...

  6. Work at DP

    转载请注明出处:http://www.cnblogs.com/TSHugh/p/8858805.html Prepared: (无notes的波兰题目的notes见我的波兰题目补全计划)BZOJ #3 ...

  7. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  8. poi2015 bzoj4377-4386训练

    就按时间顺序写吧 完成度:10/10 3.30 bzoj4385 首先一定是删去连续d个数,然后枚举终点,起点显然有单调性,用单调队列乱搞搞就可以啦 bzoj4378 首先才结论:可行当且仅当把所有大 ...

  9. BZOJ 4385: [POI2015]Wilcze doły

    4385: [POI2015]Wilcze doły Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 648  Solved: 263[Submit][ ...

随机推荐

  1. java socket编程开发简单例子 与 nio非阻塞通道

    基本socket编程 1.以下只是简单例子,没有用多线程处理,只能一发一收(由于scan.nextLine()线程会进入等待状态),使用时可以根据具体项目功能进行优化处理 2.以下代码使用了1.8新特 ...

  2. Swift - 推送之本地推送(UILocalNotification)

    // 本地推送通知是通过实例化UILocalNotification实现的.要实现本地化推送可以在AppDelegate.swift中添加代码实现,本事例是一个当App进入后台时推送一条消息给用户. ...

  3. php导出excel封装类

    因为实际情况的需要,导出excel表格在后台开发的过程中会经常用到.下面是我在实际应用中自己整理的一个导出excel类,需要PHPExcel支持,本类很好的完成导出表格的基本样式,保存路径,切换工作薄 ...

  4. ios 拨打电话

    1,这种方法,拨打完电话回不到原来的应用,会停留在通讯录里,而且是直接拨打,不弹出提示NSMutableString * str=[[NSMutableString alloc] initWithFo ...

  5. 学习SQLAlchemy Core

    有时间了就要慢慢看,死守DJANGO ORM,明显没有SQLAlchemy有优势. 因为SQLAlchemy针对整个PYTHON都是有用的. 找了本书,慢慢撸. <Essential.SQLAl ...

  6. Go1.7改善了编译速度并且会生成更快的代码

    Go1.7的开发周期正在接近它的下一个里程碑,Go的提交者Dave Cheney报告了子即将发布的版本中,团队成员在语言工具链上的努力. Cheney称,基于当前的开发状态,Go1.7将会很容易就成为 ...

  7. 在Asp.Net MVC中设定site路径所对应的默认action

    设置路由的default的Controller和Action可以达到我们预期的效果,代码如下所示: public class RouteConfig { public static void Regi ...

  8. pylab模式

    启动IPython时ipython --pylab就可以进入pylab模式,这种模式下画图时图片不会直接蹦出来,而是嵌在交互环境中,当然sypder里自动是pylab模式了

  9. python学习-爬虫

    转载自 静觅的博客 最普通下载网页 import urrlib2 response = urllib2.urlopen("http://www.baidu.com") print ...

  10. sqlserver 作业调度(作业常用的几个步骤)

    --[作业常用的几个步骤] EXEC msdb.dbo.sp_delete_job EXEC msdb.dbo.sp_add_job EXEC msdb.dbo.sp_add_jobstep EXEC ...