题意

给一颗树,删除一条边再加一条边,使它仍为一颗树且任意两点间的距离的最大值最小。

题目数据范围描述有问题,n为1或重建不能使任意两点距离最大值变小,可以输出任意答案。

分析

删除一条边后会使它变成两颗树,两棵树的直径的中点相连一定是使距离最小的

红色的边为删除重建的边

在树上dp维护每个子树的最大直径\(h[x]\),和去除这个子树后的树的最大直径\(t[x]\),u为x的父亲,删除u-x这条边并重建后的树的最大直径为

\[\max\{\frac{h[x]+1}{2}+\frac{t[x]+1}{2}+1,h[x],t[x]\}\]

设\(g[u]\)为以\(u\)为根的子树中\(u\)能到达的最远距离

设\(p[u]\)为去除以\(u\)为根的子树后\(u\)能到达的最远距离

自底向上

x为u的孩子,\(mx1\),\(mx2\)分别为\(g[x]\)的最大值和次大值

  • \(g[u]=max(g[x]+1)\)
  • \(h[u]=max\{h[x],g[u],mx1+mx2+2\}​\)

自顶向下

k为x的兄弟,\(mx1​\),\(mx2​\)分别为\(g[k]\)的最大值和次大值

  • \(p[x]=max(p[u]+1,g[k]+2)​\)
  • \(t[x]=max \{p[u],h[k],p[u]+g[k]+1,mx1+mx2+2 \}​\)

然后bfs找重建的边
实现细节很多,我写的比较乱,建议自己根据dp式子模拟一下

Code

#include<bits/stdc++.h>
#define fi first
#define se second
#define bug cout<<"--------------"<<endl
using namespace std;
typedef long long ll;
const double PI=acos(-1.0);
const double eps=1e-6;
const int inf=1e9;
const ll llf=1e18;
const int mod=1e9+7;
const int maxn=3e5+10;
int n;
vector<int>f[maxn];
typedef pair<int,int> pii;
pii e[maxn];
int g[maxn],h[maxn],p[maxn],t[maxn];
int ans=inf;
pii ans1,ans2;
void dfs1(int u,int fa){int mx1=-inf,mx2=-inf;int len=f[u].size();int po=len;for(int i=0;i<len;i++){int x=f[u][i];if(x==fa){continue;}dfs1(x,u);g[u]=max(g[x]+1,g[u]);if(g[x]>mx1){mx2=mx1;mx1=g[x];}else if(g[x]>mx2){mx2=g[x];}h[u]=max(h[u],h[x]);}h[u]=max(h[u],g[u]);h[u]=max(mx1+mx2+2,h[u]);
}
int pre[maxn],suf[maxn];
int pr[maxn],sf[maxn];
void dfs2(int u,int fa){int len=f[u].size();vector<int>q;q.push_back(0);for(int i=0;i<len+5;i++) pre[i]=suf[i]=pr[i]=sf[i]=-inf;for(int i=0;i<len;i++){int x=f[u][i];if(x!=fa) q.push_back(x);}len=q.size()-1;for(int i=1;i<=len;i++){int x=q[i];t[x]=max(t[x],t[u]);pre[i]=max(pre[i-1],g[x]);pr[i]=max(pr[i-1],h[x]);}for(int i=len;i>=1;i--){int x=q[i];suf[i]=max(suf[i+1],g[x]);sf[i]=max(sf[i+1],h[x]);        }for(int i=1;i<=len;i++){int x=q[i];p[x]=max(p[x],p[u]+1);t[x]=max(p[u],t[x]);}for(int i=2;i<=len;i++){int x=q[i];t[x]=max(p[u]+1+pre[i-1],t[x]);t[x]=max(pr[i-1],t[x]);p[x]=max(pre[i-1]+2,p[x]);}for(int i=1;i<len;i++){int x=q[i];t[x]=max(p[u]+1+suf[i+1],t[x]);t[x]=max(sf[i+1],t[x]);p[x]=max(suf[i+1]+2,p[x]);      }for(int i=2;i<len;i++){int x=q[i];t[x]=max(t[x],pre[i-1]+suf[i+1]+2);}int mx1=-inf,mx2=-inf;for(int i=1;i<=len;i++){int x=q[i];t[x]=max(mx1+mx2+2,t[x]);if(g[x]>mx1){mx2=mx1;mx1=g[x];}else if(g[x]>mx2){mx2=g[x];}}mx1=mx2=-inf;for(int i=len;i>=1;i--){int x=q[i];t[x]=max(mx1+mx2+2,t[x]);if(g[x]>mx1){mx2=mx1;mx1=g[x];}else if(g[x]>mx2){mx2=g[x];}}for(int i=1;i<=len;i++){int x=q[i];int dis=max(max(t[x],h[x]),(t[x]+1)/2+(h[x]+1)/2+1);if(dis<ans){ans=dis;ans1=pii(x,u);}}for(int i=0;i<(int)f[u].size();i++){int x=f[u][i];if(x==fa) continue;dfs2(x,u);}
}
int pe[maxn],vis[maxn];
queue<int>q;
int bfs(int fa){int ret=fa;memset(vis,0,sizeof(vis));memset(pe,0,sizeof(pe));q.push(fa);vis[fa]=1;while(!q.empty()){int u=q.front();q.pop();ret=u;int len=f[u].size();for(int i=0;i<len;i++){if(!vis[f[u][i]]){q.push(f[u][i]);pe[f[u][i]]=u;vis[f[u][i]]=1; }}}return ret;
}
int fq[maxn],tot;
void dfs(int u,int s){if(u==0) return;fq[++tot]=u;dfs(pe[u],s);
}
int find(int x){tot=0;int s=bfs(x);int t=bfs(s);dfs(t,s);return fq[(tot+1)/2];
}
void work(){for(int i=1;i<=n;i++){f[i].clear();}for(int i=1;i<n;i++){int a=e[i].fi,b=e[i].se;if(a==ans1.fi&&b==ans1.se) continue;if(b==ans1.fi&&a==ans1.se) continue;f[a].push_back(b);f[b].push_back(a);}ans2.fi=find(ans1.fi);ans2.se=find(ans1.se);cout<<ans<<endl;cout<<ans1.fi<<" "<<ans1.se<<endl;cout<<ans2.fi<<" "<<ans2.se<<endl;
}
int main(){ios::sync_with_stdio(false);//freopen("in","r",stdin);cin>>n;for(int i=1,a,b;i<n;i++){cin>>a>>b;f[a].push_back(b);f[b].push_back(a);e[i]=pii(a,b);}dfs1(1,0);dfs2(1,0);work();return 0;
}

转载于:https://www.cnblogs.com/xyq0220/p/10868968.html

BZOJ 2651 城市改建 树形DP+模拟?相关推荐

  1. 2651: 城市改建 树形DP

    我太sb了..一看输出方案就瞎jb记录了一坨信息..最后发现根本没有用.. 结果写了6.7K...成功成为了BZOJ写的最长跑的最慢的选手2333.. 题目即在一棵树上删一边加一边,使得新树的直径最小 ...

  2. bzoj 1369: Gem 树形dp

    题目大意 给出一棵树,要求你为树上的结点标上权值,权值可以是任意的正整数 唯一的限制条件是相临的两个结点不能标上相同的权值,要求一种方案,使得整棵树的总价值最小.N<=10000 题解 我们可以 ...

  3. POJ3107 Godfather 树形dp+模拟vector

    题意: Description Last years Chicago was full of gangster fights and strange murders. The chief of the ...

  4. BZOJ 4753 二分+树形DP

    思路: 先二分答案 f[x][j]表示在x的子树里选j个点 f[x][j+k]=max(f[x][j+k],f[x][j]+f[v[i]][k]); 初始化 x!=0 -> f[x][1]=p[ ...

  5. BZOJ 2133 切割(树形DP,树上背包)大概是本题全网第一篇题解 >_<【BZOJ 修复工程】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 BZOJ 2133 切割这道题全网搜不到任何一篇题解 >_< 看评测记录也没有几个人AC- ...

  6. BZOJ.3227.[SDOI2008]红黑树tree(树形DP 思路)

    BZOJ orz MilkyWay天天做sxt! 首先可以树形DP:\(f[i][j][0/1]\)表示\(i\)个点的子树中,黑高度为\(j\),根节点为红/黑节点的最小红节点数(最大同理). 转移 ...

  7. UOJ #131 BZOJ 4199 luogu P2178【NOI2015】品酒大会 (后缀自动机、树形DP)

    UOJ #131 BZOJ 4199 luogu P2178[NOI2015]品酒大会 (后缀自动机.树形DP) 水是水,但是写出了不少问题,因此写一发博客. https://www.luogu.or ...

  8. BZOJ.4199.[NOI2015]品酒大会(后缀自动机 树形DP)

    BZOJ 洛谷 后缀数组做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 只考虑求极长相同子串,即所有后缀之间的LCP. 而后缀的LCP在后缀树的LCA处.同差异这道题,在每个点处 ...

  9. 2011分区联赛模拟试题 电子眼(树形dp)

    2011分区联赛模拟试题 电子眼 Description 中山市石一个环境优美.气候宜人的小城市.因为城市的交通并不繁忙,市内的道路网很稀疏.准确地说,中山市有N-1条马路和N个路口,每条马路连接两个 ...

最新文章

  1. zTree实现节点修改的实时刷新
  2. SVN常用命令及在windows上安装SVN
  3. spotify 数据分析_没有数据? 没问题! 如何从Wikipedia和Spotify收集重金属数据
  4. python3能做什么_你都用 Python 来做什么?
  5. 括号表示法字符串构造二叉树_一篇文章学会二叉树和二叉查找树
  6. 对于计算机专业的调查报告,计算机专业调查报告.doc
  7. VS11中添加PagedList引用
  8. 我们应该如何去了解JavaScript引擎的工作原理
  9. VMware虚拟机下载及安装教程
  10. ddr42400和2660混插_DDR4 3000与DDR4 3200性能相差多少?为什么不能混插使用?
  11. SSM项目使用ConfigTools对数据库的密码进行加密
  12. 如何将pdf转换成txt转换器破解版
  13. 在线产品经理实习 任务三:给搜狐新闻24小时热点做一份产品说明文档
  14. Moment.js 2.22.2 源代码
  15. NR PRACH(五) type1 RA(4-step)基本过程
  16. 都柏林硕士计算机英文,都柏林大学计算机硕士4月22号、23号上海、北京面试,现场发录取…...
  17. Android 内置RTSP/RTMP服务器,实现局域网内视频推流与播放
  18. Docker学习01---狂神说
  19. PMP证书到期,有必要续证吗?
  20. SPI中NSS/CS使用和SPI常见问题

热门文章

  1. Verilog 自动饮料售卖机
  2. 川教版计算机四年级上教案,川教版四年级上册信息技术教学计划
  3. 王道计算机网络知识点整理
  4. IOS入门学习视频教程
  5. oracle 每月同期对比,两年数据同期对比表_月份对比表格怎么做
  6. nvidia 服务器芯片组,nVIDIA发布nForce Professional芯片组
  7. mysql json decode_json_decode函数详解
  8. linux/Centos 安装GTX-1080Ti 显卡 配置显卡驱动 cuda cudnn
  9. 安卓配置多渠道包error:All flavors must now belong to a named flavor dimension
  10. 卡西欧计算机亮度,卡西欧手表灯光怎么调 卡西欧手表灯光亮度可以调吗