[TJOI2017]城市(树的直径)
[TJOI2017]城市
题目描述
从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作。这个地区一共有ri座城市,《-1条高速公路,保证了任意两运城市之间都可以通过高速公路相互可达,但是通过一条高速公路需要收取一定的交通费用。小明对这个地区深入研究后,觉得这个地区的交通费用太贵。小明想彻底改造这个地区,但是由于上司给他的资源有限,因而小明现在只能对一条高速公路进行改造,改造的方式就是去掉一条高速公路,并且重新修建一条一样的高速公路(即交通费用一样),使得这个地区的两个城市之间的最大交通费用最小(即使得交通费用最大的两座城市之间的交通费用最小),并且保证修建完之后任意两座城市相互可达。如果你是小明,你怎么解决这个问题?
输入输出格式
输入格式:
输入数据的第一行为一个整数n,代表城市个数。
接下来的n - 1行分别代表了最初的n-1条公路情况。每一行都有三个整数u,v,d。u,v代表这条公路的两端城市标号,d代表这条公路的交通费用。
1 <= u,v <= n,1<= d <= 2000
输出格式:
输出数据仅有一行,一个整数,表示进行了最优的改造之后,该地区两城市 之间最大交通费用。
输入输出样例
输入样例#1: 复制
5
1 2 1
2 3 2
3 4 3
4 5 4
输出样例#1: 复制
7
说明
对于30%的数据,1<=n<500
对于100%的数据,1<=n<=5000
题解
友善的讲解一下.
断开一个点之后,我们只需要求出两个联通块的直径。
然后我们要保证断开的公路连接的两个联通块的半径最大值最小,这样能新生成的树的直径在这三个值中最小。
这个题目不难,难在我脑抽...直接照搬了[NOI2003]逃学的小孩的方法去写。但是我忘了其实点要在两个联通块的直径上才能求半径,不在直径上会影响半径的求取。
调了三天,看崩了几个人,常数极其大(可以优化但我懒得写了)。吸氧能过。
代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=5001;
struct node{
int to,nex,v;
}e[N<<1];
int num,head[N];
int dir[N],dis[N],r1,r2,s1,s2,t1,t2;
int n,m,ans=99999999,maxn1,maxn2;
int x[N],y[N],z[N],vis[N],ff[N];
int read(){
int x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
}
void add(int from,int to,int v){
num++;
e[num].to=to;
e[num].v=v;
e[num].nex=head[from];
head[from]=num;
}
void dfs(int x,int fa){
for(int i=head[x];i;i=e[i].nex){
int v=e[i].to;if(v==fa)continue;ff[v]=x;
dis[v]=dis[x]+e[i].v;dfs(v,x);
}
}
void dfs2(int x,int fa){
for(int i=head[x];i;i=e[i].nex){
int v=e[i].to;if(v==fa)continue;
dir[v]=dir[x]+e[i].v;dfs2(v,x);
}
}
void clear(){
memset(e,0,sizeof(e));memset(head,0,sizeof(head));num=0;
r1=r2=maxn1=maxn2=0;
}
void solve(int now){
for(int i=1;i<n;i++)
if(i!=now)add(x[i],y[i],z[i]),add(y[i],x[i],z[i]);
dfs(x[now],0);for(int i=1;i<=n;i++){if(dis[i]>maxn1)maxn1=dis[i],s1=i;ff[i]=dis[i]=0;}
dfs(s1,0);maxn1=0;for(int i=1;i<=n;i++){if(dis[i]>maxn1)maxn1=dis[i],t1=i;}
int tmp=t1;while(tmp){vis[tmp]=1;tmp=ff[tmp];}
dfs2(t1,0);for(int i=1;i<=n;i++)
{if(vis[i])r1=max(r1,min(dis[i],dir[i]));
vis[i]=ff[i]=dis[i]=dir[i]=0;}
dfs(y[now],0);for(int i=1;i<=n;i++){if(dis[i]>maxn2)maxn2=dis[i],s2=i;ff[i]=dis[i]=0;}
dfs(s2,0);maxn2=0;for(int i=1;i<=n;i++){if(dis[i]>maxn2)maxn2=dis[i],t2=i;}
tmp=t2;while(tmp){vis[tmp]=1;tmp=ff[tmp];}
dfs2(t2,0);for(int i=1;i<=n;i++){if(vis[i])r2=max(r2,min(dis[i],dir[i]));vis[i]=ff[i]=dis[i]=dir[i]=0;}
ans=min(ans,max(maxn1,max(maxn2,maxn1+maxn2-r1-r2+z[now])));
clear();
}
int main(){
// freopen("data.in","r",stdin);
// freopen("ans.out","w",stdout);
n=read();
for(int i=1;i<n;i++){
x[i]=read(),y[i]=read(),z[i]=read();
}
for(int i=1;i<n;i++)
solve(i);
printf("%d\n",ans);
return 0;
}
[TJOI2017]城市(树的直径)的更多相关文章
- [TJOI2017] 城市 (树的直径,贪心)
题目链接 Solution 这道题,调了我一晚上... 一直80分 >_<|| ... 考虑到几点: 分开任意一条边 \(u\) ,那么其肯定会断成两棵树. 肯定是分开直径上的边最优,否则 ...
- luogu P3761 [TJOI2017]城市 树的直径 bfs
LINK:城市 谢邀,学弟说的一道毒瘤题. 没有真正的省选题目毒瘤 或者说 写O(n)的做法确实毒瘤. 这里给一个花20min就写完的非常好写的暴力. 容易想到枚举哪条边删掉 删掉之后考虑在哪两个点上 ...
- bzoj4890[Tjoi2017]城市(树的半径)
4890: [Tjoi2017]城市 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 149 Solved: 91[Submit][Status][D ...
- [LOJ3014][JOI 2019 Final]独特的城市——树的直径+长链剖分
题目链接: [JOI 2019 Final]独特的城市 对于每个点,它的答案最大就是与它距离最远的点的距离. 而如果与它距离为$x$的点有大于等于两个,那么与它距离小于等于$x$的点都不会被计入答案. ...
- LG5536 「XR-3」核心城市 树的直径
问题描述 LG5536 题解 两次 \(\mathrm{dfs}\) 求树的直径. 然后找到树的直径的中点. 然后按照 子树中最深的点深度-自己深度 排序,贪心选取前 \(k\) 个. \(\math ...
- 换根DP+树的直径【洛谷P3761】 [TJOI2017]城市
P3761 [TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速公 ...
- [TJOI2017]城市 【树的直径+暴力+优化】
Online Judge:Luogu P3761 Label:树的直径,暴力 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有n座城市,n-1条高速公路,保证了 ...
- 【BZOJ4890】[TJOI2017]城市(动态规划)
[BZOJ4890][TJOI2017]城市(动态规划) 题面 BZOJ 洛谷 题解 数据范围都这样了,显然可以暴力枚举断开哪条边. 然后求出两侧直径,暴力在直径上面找到一个点,使得其距离直径两端点的 ...
- [洛谷P3761] [TJOI2017]城市
洛谷题目链接:[TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速 ...
随机推荐
- 51nod 1785 数据流中的算法 (方差计算公式)
1785 数据流中的算法 基准时间限制:1.5 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 51nod近日上线了用户满意度检测工具,使用高级人工智能算法,通过用户访问时间.鼠 ...
- 51nod-1134 最长递增子序列,用线段树将N^2的dp降到NlogN
题目链接 给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递增的) 例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10. Input 第1行 ...
- servlet中Session的用法
## (1)什么是Session? 服务器端为了保存用户的状态而创建的一个特殊的对象(即session对象). 当浏览器第一次访问服务器时,服务器会创建session对象(该 ...
- LAMP 建立 Wordpress 站点 Linux Apache MariaDB PHP
使用LAMP建立Wordpress, 要求如下: 准备工作: VMware 14 CentOS 7.4 最小化 安装镜像 Wordpress 安装包, 下载 预热: 使用VMware新建4台虚拟机, ...
- 洛谷P3834 【模板】可持久化线段树 1 主席树
Code: #include<cstdio> #include<algorithm> using namespace std; const int maxn = 2000000 ...
- 路飞学城Python-Day13
[2.常用模块-模块的种类和导入方法] 1.什么是模块? 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长.越来越不容易维护. 为了编写可维护的代码,我们把很多函数分组,分 ...
- How Javascript works (Javascript工作原理) (二) 引擎,运行时,如何在 V8 引擎中书写最优代码的 5 条小技巧
个人总结: 一个Javascript引擎由一个标准解释程序,或者即时编译器来实现. 解释器(Interpreter): 解释一行,执行一行. 编译器(Compiler): 全部编译成机器码,统一执行. ...
- css 遮照镂空效果
实现这个效果有以下几种方式.(欢迎指出不足之处!!!) 一:最简单最粗暴的方法!截图! 实现原理:先截一张图片,然后写一个遮罩层,再把图片放上去就可以了! 过程过于简单,就别写代码跟截图效果了! 优 ...
- 管理windows自启动程序
1. 点击开始,在运行程序框中输入msconfig,然后回车. 在弹出的对话框中,点击”启动“选项卡,在启动项目列表中,把不需要的启动项目前面的对号去掉. 然后切换到”服务“选项卡,这里的服务项目列表 ...
- Adobe AIR and Flex - 保存序列化对象文件(译)
创建任何桌面应用程序几乎总是需要在本地存储数据,通过Adobe AIR我们有几下面几个选择,一个是我们能够使用内置的 SQLite 数据库支持,对于少量的数据这是大材小用了.另外一个选择是我们通过把数 ...