luogu P3761 [TJOI2017]城市 树的直径 bfs
LINK:城市
谢邀,学弟说的一道毒瘤题。
没有真正的省选题目毒瘤 或者说 写O(n)的做法确实毒瘤。
这里给一个花20min就写完的非常好写的暴力。
容易想到枚举哪条边删掉 删掉之后考虑在哪两个点上加。
一个比较重要的性质是 联通两个连通块之后 大联通块的直径端点一定有一端属于原来两个联通块的直径端点之一。
也就是合并两个连通块 直径等于=max(左边直径,右边直径,链接起来的直径)
其中前两者固定 考虑让第三者最小 进一步可以分析得到 那两个点的贡献是到自己连通块内的最长距离的点。
分别最小化之后显然是直径上的中点。
一个比较有意思的事实:实际上直径的中点可能在两个节点之间 那么此时这两个节点的贡献相同 所以选哪个都行。
沿着直径找中点过于繁琐 可以直接从直径两端bfs 然后每个点的贡献为max(dis1[x],dis2[x]).
这样就很好写了。值得一提的是 我的写法没有加入过多的优化 每次需要6遍bfs,所以常数有点大。
卡常:容易发现 如果删的不是直径上的边那么对答案没有贡献 可以直接枚举删直径上的边。
考虑求出左边的直径之后进行最优性剪枝 比当前答案大就没必要再做了。
进一步的可以将bfs的次数卡一下 只删直径上的边之后 一个比较重要的性质是 原来树中的直径依然还是分属两个连通块的两端。
这样bfs的次数只有4次了。
进一步的 可以由此推出O(n)的做法 沿着直径删边 然后 每次便利多出来的部分 由上次直径推出当前直径 复杂度就降到O(n)了 不过实现起来过于繁琐 我就没实现。
经过优化的code:n^2 十个测试点跑了400多ms 我也很骄傲~
const int MAXN=5010;
int n,ans,id,flag,len=1,t,h,c1,c2;
int vis[MAXN],c[MAXN<<1],dis[MAXN],q[MAXN],dis1[MAXN],s1,s2,s3,mark;
int lin[MAXN],e[MAXN<<1],ver[MAXN<<1],nex[MAXN<<1];
inline void add(int x,int y,int z)
{
ver[++len]=y;
nex[len]=lin[x];
lin[x]=len;
e[len]=z;
}
inline int bfs(int s)
{
++id;t=h=0;int mx=0,p=s;
q[++t]=s;vis[s]=id;dis[s]=0;
while(++h<=t)
{
int x=q[h];
go(x)
{
if(i==(mark^1)||i==mark)continue;
if(vis[tn]!=id)
{
vis[tn]=id;
dis[tn]=dis[x]+e[i];
q[++t]=tn;
if(dis[tn]>mx)mx=dis[tn],p=tn;
}
}
}
return p;
}
inline void bfs1(int s,int &w)
{
++id;t=h=0;w=INF;
q[++t]=s;vis[s]=id;dis1[s]=0;
while(++h<=t)
{
int x=q[h];
w=min(w,max(dis[x],dis1[x]));
go(x)
{
if(i==(mark^1)||i==mark)continue;
if(vis[tn]!=id)
{
vis[tn]=id;
dis1[tn]=dis1[x]+e[i];
q[++t]=tn;
}
}
}
}
inline void dfs(int x,int fa)
{
if(x==c2){flag=1;return;}
go(x)
if(tn!=fa)
{
dfs(tn,x);
if(flag)
{
c[i]=c[i^1]=1;
return;
}
}
}
int main()
{
freopen("1.in","r",stdin);
get(n);
rep(2,n,i)
{
int get(x),get(y),get(z);
add(x,y,z);add(y,x,z);
}
c1=bfs(1);c2=bfs(c1);
dfs(c1,0);ans=dis[c2];
for(int i=2;i<=len;i+=2)
{
if(!c[i])continue;
mark=i;
int w1=bfs(c1);
if(dis[w1]>=ans)continue;
bfs1(w1,s1);
int w2=bfs(c2);
if(dis[w2]>=ans)continue;
bfs1(w2,s2);
ans=min(ans,max(dis[w1],max(dis[w2],s2+s1+e[i])));
}
put(ans);return 0;
}
luogu P3761 [TJOI2017]城市 树的直径 bfs的更多相关文章
- [TJOI2017] 城市 (树的直径,贪心)
题目链接 Solution 这道题,调了我一晚上... 一直80分 >_<|| ... 考虑到几点: 分开任意一条边 \(u\) ,那么其肯定会断成两棵树. 肯定是分开直径上的边最优,否则 ...
- poj2631 树的直径 + bfs
//Accepted 492 KB 0 ms //树的直径 bfs #include <cstdio> #include <cstring> #include <iost ...
- [洛谷P3761] [TJOI2017]城市
洛谷题目链接:[TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速 ...
- bzoj4890[Tjoi2017]城市(树的半径)
4890: [Tjoi2017]城市 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 149 Solved: 91[Submit][Status][D ...
- hdu2196 树的直径 + bfs
//Accepted 740 KB 15 ms //树的直径 //距离一个顶点最远的点一定是树的直径的一个端点 #include <cstdio> #include <cstring ...
- [LOJ3014][JOI 2019 Final]独特的城市——树的直径+长链剖分
题目链接: [JOI 2019 Final]独特的城市 对于每个点,它的答案最大就是与它距离最远的点的距离. 而如果与它距离为$x$的点有大于等于两个,那么与它距离小于等于$x$的点都不会被计入答案. ...
- LG5536 「XR-3」核心城市 树的直径
问题描述 LG5536 题解 两次 \(\mathrm{dfs}\) 求树的直径. 然后找到树的直径的中点. 然后按照 子树中最深的点深度-自己深度 排序,贪心选取前 \(k\) 个. \(\math ...
- 树上选两点(使最短)树的直径+bfs
题意: 给你一颗树,让你放两个点,放在哪里的时候任意点到某个最近的消防站最远值最小. 思路: 树的直径类题目. 首先我们想两个点会把整棵树分成两个团,所以肯定会在树的某个链上切开. 而且要切一定切在树 ...
- ZOJ 3820 Building Fire Stations 求中点+树的直径+BFS
题意:给一棵树,要求找出两个点,使得所有点到这两个点中距离与自己较近的一个点的距离的最大值(所有点的结果取最大的值,即最远距离)最小. 意思应该都能明白. 解法:考虑将这棵树摆直如下: 那么我们可以把 ...
随机推荐
- Emergency Evacuation 题解
The Japanese government plans to increase the number of inbound tourists to forty million in the yea ...
- Hyperledger Fabric 2.1 搭建教程
Hyperledger Fabric 2.1 搭建教程 环境准备 版本 Ubuntu 18.04 go 1.14.4 fabric 2.1 fabric-sample v1.4.4 nodejs 12 ...
- Java入门系列之final
前言 在C#经典面试中掺杂过Java的final关键字,主要用于类不能被继承,在C#则是利用关键字seal修饰类为密封类,而在Java中的final关键字的具体用法包含C#中const.readonl ...
- 前端08 /jQuery标签操作、事件
前端08 /jQuery标签操作.事件 目录 前端08 /jQuery标签操作.事件 1.标签内文本操作 1.1 html标签元素中的所有内容 1.2 text 标签元素的文本内容 2.文档标签操作 ...
- ArcGIS 10.2安装及卸载教程
卸载 在控制面板中找到程序->卸载程序 找到ArcGIS的相关软件 这里以ArcGIS 10.2 Destop为例,选中,然后点击卸载,会出现如下界面 选择Remove,然后根据提示进行操作,即 ...
- Kite: 一个分布式微服务框架(翻译)
原文链接:https://blog.gopheracademy.com/birthday-bash-2014/kite-microservice-library/ 此为中文翻译 用GO语言来编写web ...
- SpringCloud全家桶介绍及手绘架构
文章目录 概述 一.业务场景介绍 二.Spring Cloud核心组件:Eureka 三.Spring Cloud核心组件:Feign 四.Spring Cloud核心组件:Ribbon 五.Spri ...
- Websphere修改web.xml不生效的解决办法(转)
在websphere下部署了一个java工程后,如果修改了web.xml文件,重新启动这个java工程发现websphere并没有自动加载web.xml文件,即修改后的web.xml并不起作用,除非重 ...
- Intelij DataGrip 的安装和使用
链接: Intelij DataGrip 安装教程以及汉化教程 Intelij DataGrip 使用教程 以上两个教程已使用过,没有问题 如有侵权请联系删除
- C++语法小记---经典问题之一(一个空类包含什么)
问题:一个空类包含什么 空的构造函数 拷贝构造函数(浅拷贝) 重载赋值操作符函数(浅拷贝) 析构函数 取址运算符 取址运算符const 注意 所有的这些默认函数,只有在代码中调用了才会生成,否则也不会 ...