画个图意会一下,对于每条边,砍掉它后再把这两棵树接起来,新树的最小直径是两棵树最大直径/2(上取整)的和+1,最大值是直径的和
所以对于每条边都求出它分开的两棵树的直径,找到最小最大值后随便搜一下就行了
emmmmmmmmmmmmmmm
dp的过程细节挺爆炸的

code:

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define lowbit(x) x&(-x)
using namespace std;inline void read(int &x)
{char c; while(!((c=getchar())>='0'&&c<='9'));x=c-'0';while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
}
inline void up(int &x,const int &y){if(x<y)x=y;}
const int maxn = 1100000;int n;
vector<int>V[maxn];
inline void ins(const int x,const int y){V[x].push_back(y);}int fa[maxn],f[maxn],g[maxn];
void dfs(const int x)
{f[x]=g[x]=0;for(int i=0;i<V[x].size();i++){int y=V[x][i]; if(y==fa[x]) continue;fa[y]=x;dfs(y);up(g[x],max(g[y],f[x]+f[y]+1));up(f[x],f[y]+1);}
}
int u[maxn],ug[maxn];
int pre[maxn],preg[maxn],suf[maxn],sufg[maxn];
int ans1,X1,Y1,ans2,X2,Y2;
void dfs2(const int x)
{for(int i=0;i<V[x].size();i++){int y=V[x][i];pre[i+1]=max(pre[i],y==fa[x]?0:f[y]+1),preg[i+1]=max(preg[i],y==fa[x]?0:max(pre[i]+f[y]+1,g[y]));}suf[V[x].size()]=0; sufg[V[x].size()]=0;for(int i=V[x].size()-1;i>=0;i--){int y=V[x][i];suf[i]=max(suf[i+1],y==fa[x]?0:f[y]+1),sufg[i]=max(sufg[i+1],y==fa[x]?0:max(suf[i+1]+f[y]+1,g[y]));}for(int i=0;i<V[x].size();i++) if(V[x][i]!=fa[x]){int y=V[x][i];int now=max(pre[i]+suf[i+1],u[x]+max(pre[i],suf[i+1])); up(now,ug[x]); up(now,preg[i]); up(now,sufg[i+1]);up(ug[y],now);int temp=(now+1)/2+(g[y]+1)/2+1;up(temp,now); up(temp,g[y]);if(temp<ans1) ans1=temp,Y1=y;temp=now+g[y]+1;if(temp>ans2) ans2=temp,Y2=y;u[y]=max(pre[i],suf[i+1])+1; up(u[y],u[x]+1);}for(int i=0;i<V[x].size();i++) if(V[x][i]!=fa[x]) dfs2(V[x][i]);
}
void trans(const int x)
{f[x]=g[x]=0;for(int i=0;i<V[x].size();i++) if(V[x][i]!=fa[x]){int y=V[x][i]; fa[y]=x; trans(y); up(g[x],g[y]); up(g[x],f[x]+f[y]+1); up(f[x],f[y]+1);}
}
int root,standard;
void search(const int x)
{bool flag=true;if(u[x]>standard) flag=false;for(int i=0;i<V[x].size()&&flag;i++) if(V[x][i]!=fa[x])if(f[V[x][i]]+1>standard) flag=false;if(flag) { root=x; return; }for(int i=0;i<V[x].size();i++)pre[i+1]=max(pre[i],V[x][i]==fa[x]?0:f[V[x][i]]+1);suf[V[x].size()]=0;for(int i=V[x].size()-1;i>=0;i--)suf[i]=max(suf[i+1],V[x][i]==fa[x]?0:f[V[x][i]]+1);for(int i=0;i<V[x].size();i++) if(V[x][i]!=fa[x]){int y=V[x][i];u[y]=max(pre[i],suf[i+1])+1; up(u[y],u[x]+1);}for(int i=0;i<V[x].size()&&root==-1;i++) if(V[x][i]!=fa[x]) search(V[x][i]);
}
void search2(const int x)
{if(u[x]==standard) { root=x; return; }for(int i=0;i<V[x].size();i++)pre[i+1]=max(pre[i],V[x][i]==fa[x]?0:f[V[x][i]]+1);suf[V[x].size()]=0;for(int i=V[x].size()-1;i>=0;i--)suf[i]=max(suf[i+1],V[x][i]==fa[x]?0:f[V[x][i]]+1);for(int i=0;i<V[x].size();i++) if(V[x][i]!=fa[x]){int y=V[x][i];u[y]=max(pre[i],suf[i+1])+1; up(u[y],u[x]+1);}for(int i=0;i<V[x].size()&&root==-1;i++) if(V[x][i]!=fa[x]) search2(V[x][i]);
}
void solve1()
{printf("%d %d %d ",ans1,X1,Y1);fa[X1]=Y1; fa[Y1]=X1;trans(X1); trans(Y1);root=-1; u[X1]=0; standard=(g[X1]+1)/2; search(X1); printf("%d ",root);root=-1; u[Y1]=0; standard=(g[Y1]+1)/2; search(Y1); printf("%d\n",root);
}
void solve2()
{printf("%d %d %d ",ans2,X2,Y2);fa[X2]=Y2; fa[Y2]=X2;trans(X2); trans(Y2);root=-1; u[X2]=0; standard=g[X2]; search2(X2); printf("%d ",root);root=-1; u[Y2]=0; standard=g[Y2]; search2(Y2); printf("%d\n",root);
}int main()
{read(n);for(int i=1;i<n;i++){int x,y; read(x); read(y);ins(x,y); ins(y,x);}fa[1]=0; dfs(1);u[1]=0; ans1=2*n,ans2=-1;dfs2(1); X1=fa[Y1]; X2=fa[Y2];solve1(); solve2();return 0;
}

BZOJ4379: [POI2015]Modernizacja autostrady相关推荐

  1. BZOJ4379[POI2015] Modernizacja autostrady

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

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

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

  3. BZOJ4379 : [POI2015]Modernizacja autostrady

    两遍树形DP求出每个点开始往上往下走的前3长路以及每个点上下部分的直径. 枚举每条边断开,设两边直径分别为$A,B$,则: 对于第一问,连接两边直径的中点可得直径为$\max(A,B,\lfloor\ ...

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

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

  5. 【BZOJ 3747】 3747: [POI2015]Kinoman (线段树)

    3747: [POI2015]Kinoman Time Limit: 60 Sec  Memory Limit: 128 MB Submit: 830  Solved: 338 Description ...

  6. [POI2015]CZA

    [POI2015]CZA p很小,讨论 p=0... p=1... p=2:n-1放左或者放右两种情况,剩下怎么放是固定的,模拟然后判断即可 p=3: 正着做要状压,类似放书和排座位那些题,考虑以某个 ...

  7. P3591 [POI2015]ODW(分块)

    P3591 [POI2015]ODW 给定一颗有nnn个节点的树,点有点权,给定一个长度为nnn的排列ppp,给定一个长度为n−1n - 1n−1的数组ccc, 我们会在树上进行n−1n - 1n−1 ...

  8. bzoj4380[POI2015]Myjnie dp

    [POI2015]Myjnie Time Limit: 40 Sec  Memory Limit: 256 MBSec  Special Judge Submit: 368  Solved: 185 ...

  9. BZOJ 3747 POI2015 Kinoman 段树

    标题效果:有m点,每个点都有一个权值.现在我们有这个m为点的长度n该序列,寻求区间,它仅出现一次在正确的点区间内值和最大 想了很久,甚至神标题,奔说是水的问题--我醉了 枚举左点 对于每个请求留点右键 ...

最新文章

  1. 朱俊彦团队提出GAN压缩算法:计算量减少20倍,生成效果不变,GPU、CPU统统能加速...
  2. Mysql Replication 机制
  3. 基于Delphi API写的UDP通讯类
  4. hdu2089 不要62 数位dp
  5. OpenCV霍夫直线检测的实例(附完整代码)
  6. Java多线程与并发库高级应用 学习笔记 1-9课
  7. 轩辕剑之天之痕1-5java_轩辕剑游戏 轩辕剑1到5全系列下载
  8. 【分布式】分布式架构-ESB SOA
  9. 学习计划(11.5)
  10. WMS智能仓储系统成长史?
  11. Tampermonkey 编写一个首页跳转的脚本
  12. feign 多个参数放对象_feign架构 原理解析
  13. python tts库_python 使用百度tts 库合成语音
  14. android 锁屏界面来电话,android锁屏界面短信解锁指向怎么修改?
  15. [C++]求模与求余运算
  16. 分享10款效果惊艳的HTML5图片特效
  17. 双目立体匹配之代价聚合
  18. java随机百分比_java随机百分比
  19. 网站SEO优化工具大全推荐-免费SEO优化工具
  20. Xilinx FPGA “打一拍”“打两拍”以及IOB含义

热门文章

  1. css消除点击或长按后的蓝色背景框
  2. MATLAB中:冒号用法
  3. 微信小程序 保存图片 wx.saveImageToPhotosAlbum
  4. FTP连接时出现“227 Entering Passive Mode” 的解决方法(附加实际案例)
  5. 抖音获客源码,短视频获客系统,获客SaaS有标准答案吗?
  6. pip下载镜像源汇总
  7. 边缘计算和云计算之间,主要有什么优势?
  8. 冯建文《数字电路设计》读书笔记
  9. 使用浏览器转化ASCII码为字符
  10. Android 引导页开发管理2