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
题意:给一棵树,要求找出两个点,使得所有点到这两个点中距离与自己较近的一个点的距离的最大值(所有点的结果取最大的值,即最远距离)最小. 意思应该都能明白. 解法:考虑将这棵树摆直如下: 那么我们可以把 ...
随机推荐
- Java面向对象—常见面试题
2. Java 面向对象 2.1. 类和对象 2.1.1. 面向对象和面向过程的区别 面向过程 :面向过程性能比面向对象高. 因为类调用时需要实例化,开销比较大,比较消耗资源,所以当性能是最重要的考量 ...
- Qt-文件系统
1 简介 参考视频:https://www.bilibili.com/video/BV1XW411x7NU?p=45 参考文档:<Qt教程.docx> 说明:本文主要介绍Qt的文件系统. ...
- 小白pytorch安装以及初步了解
安装遇到的几个坑: 1创建虚拟环境的时候出现Proceed ([y]/n)? 询问你是否覆盖旧版本,在命令行输入y即可进行下一步的安装操作了 安装pytorch前先了解 pytorch:一个开源pyt ...
- ::before 和 :after 中双冒号和单冒号有什么区别?
在 CSS 中伪类一直用 : 表示,如 :hover, :active 等 伪元素在CSS1中已存在,当时语法是用 : 表示,如 :before 和 :after 后来在CSS3中修订,伪元素用 :: ...
- devtools 判断类数组的方法
var obj = { '2': 3, '3': 4, 'length': 2, 'splice': Array.prototype.splice, 'push': Array.prototype.p ...
- 数据可视化之PowerQuery篇(十九)PowerBI数据分析实践第三弹 | 趋势分析法
https://zhuanlan.zhihu.com/p/133484654 本文为星球嘉宾"海艳"的PowerBI数据分析工作实践系列分享之三,她深入浅出的介绍了PowerBI ...
- GPO - General GPO Settings(2)
Creating local folders and copying files Mapping printers via GPO Deny logon locally. Installation ...
- OSCP Learning Notes - File Transfers(3)
Metasploit Attack Target Server: IE8 on WinXP 1.Start the Metasploit. setoolkit 2.Select 2)Website A ...
- C# 判断和创建目录路径
在进行一些导出或下载时,需要创建一个本地路径,以供文件进行下载和创建. if (Directory.Exists(Server.MapPath("~/upimg/hufu")) = ...
- MongoDB 事务,复制和分片的关系
摘要:本文尝试对Mongo的复制和分布式事务的原理进行描述,在必要的地方,对实现的正确性进行论证,希望能为MongoDB内核爱好者提供一些参考. 1.前言 MongoDB基于wiredTiger提供的 ...