BZOJ4379 : [POI2015]Modernizacja autostrady
两遍树形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的更多相关文章
- [BZOJ4379][POI2015]Modernizacja autostrady[树的直径+换根dp]
题意 给定一棵 \(n\) 个节点的树,可以断掉一条边再连接任意两个点,询问新构成的树的直径的最小和最大值. \(n\leq 5\times 10^5\) . 分析 记断掉一条边之后两棵树的直径为 \ ...
- 【BZOJ4379】[POI2015]Modernizacja autostrady 树形DP
[BZOJ4379][POI2015]Modernizacja autostrady Description 给定一棵无根树,边权都是1,请去掉一条边并加上一条新边,定义直径为最远的两个点的距离,请输 ...
- @bzoj - 4379@ [POI2015] Modernizacja autostrady
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一棵无根树,边权都是1,请去掉一条边并加上一条新边,定义直径 ...
- POI2015题解
POI2015题解 吐槽一下为什么POI2015开始就成了破烂波兰文题目名了啊... 咕了一道3748没写打表题没什么意思,还剩\(BZOJ\)上的\(14\)道题. [BZOJ3746][POI20 ...
- [Poi2015]
[POI2015]Łasuchy 一看以为是sb题 简单来说就是每个人获得热量要尽量多 不能找别人 首先这道题好像我自己找不到NIE的情况 很容易想到一个优化 如果一个数/2>另一个数 那么一定 ...
- Work at DP
转载请注明出处:http://www.cnblogs.com/TSHugh/p/8858805.html Prepared: (无notes的波兰题目的notes见我的波兰题目补全计划)BZOJ #3 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- poi2015 bzoj4377-4386训练
就按时间顺序写吧 完成度:10/10 3.30 bzoj4385 首先一定是删去连续d个数,然后枚举终点,起点显然有单调性,用单调队列乱搞搞就可以啦 bzoj4378 首先才结论:可行当且仅当把所有大 ...
- BZOJ 4385: [POI2015]Wilcze doły
4385: [POI2015]Wilcze doły Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 648 Solved: 263[Submit][ ...
随机推荐
- Git的一些实用操作
Ref:http://stackoverflow.com/questions/17195861/undo-git-update-index-assume-unchanged-file 1. 添加本地忽 ...
- app推送方案
--方案原理 1.轮询(Pull)方式:客户端定时向服务器发送询问消息,一旦服务器有变化则立即同步消息.但这种方式对服务器的压力太大,且比较费客户端的流量,就是不断地向服务器发送请求,但是这样开发很简 ...
- C语言文件操作相关函数
在实际应用中,我们往往需要对文件进行操作,下面我将介绍C语言的一些关于操作文件的函数. 一.计算机文件 计算机文件是以计算机硬盘为载体存储在计算机上的信息集合,是存储在某种长期储存设备上的一段数据流. ...
- IT人学习方法论(三):高效学习
一些有关“怎么学”的建议 首先需要明确方向,否则即使学习方法再高效,也不免南辕北辙,背离自己的目标.关于学习方向的讨论,请参见之前的一篇文章 .下面我来重点说一说有关“怎么学”的建议. IT技术,不是 ...
- Jmeter 中通过(_time函数)获取10位时间戳的方法
meter的__time函数作用是取当前时间的时间戳,默认取的时间精确到了毫秒级别,所以获取的时间戳默认是13位的. 下图为取10位的时间戳的函数表达式(时间精确到秒)
- 清空mysql的历史记录
# vi ~/.mysql_history show tables; show databases; 清空里面的内容,并不用退出当前shell,就可以清除历史命令!!
- Clr Via C#读书笔记---计算限制的异步操作
线程池基础 1,线程的创建和销毁是一个昂贵的操作,线程调度以及上下文切换耗费时间和内存资源. 2,线程池是一个线程集合,供应你的用程序使用. 3,每个CLR有一个自己的线程池,线程池由CLR控制的所有 ...
- 重温WCF之消息契约(MessageContract)(六)
对于SOAP来说主要由两部分构成Header和Body,他们两个共同构成了SOAP的信封,通常来说Body保存具体的数据内容,Header保存一些上下文信息或关键信息.比如:在一些情况下,具有这样的要 ...
- android:installLocation = "auto" 的用法
在Froyo(android 2.2,API Level:8)中引入了android:installLocation.通过设置该属性可以使得开发者以及用户决定程序的安装位置. android:inst ...
- Log4Net配置以及使用
跟踪程序代码,及时发现程序的运行状态,是每个成熟的软件所必不可少的一个环节,网站发布到真实的环境之后,对于程序的运行状态,我们并不能想开发环境那也,点击调试.日志记录显示就尤为重要,在.NET中记录日 ...