BZOJ3242/UOJ126 [Noi2013]快餐店
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
Description
小T打算在城市C开设一家外送快餐店。送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方。 快餐店的顾客分布在城市C的N 个建筑中,这N 个建筑通过恰好N 条双向道路连接起来,不存在任何两条道路连接了相同的两个建筑。任意两个建筑之间至少存在一条由双向道路连接而成的路径。小T的快餐店可以开设在任一建筑中,也可以开设在任意一条道路的某个位置上(该位置与道路两端的建筑的距离不一定是整数)。 现给定城市C的地图(道路分布及其长度),请找出最佳的快餐店选址,输出其与最远的顾客之间的距离。
Input
第一行包含一个整数N,表示城市C中的建筑和道路数目。
接下来N行,每行3个整数,Ai,Bi,Li(1≤i≤N;Li>0),表示一条道路连接了建筑Ai与Bi,其长度为Li 。
Output
仅包含一个实数,四舍五入保留恰好一位小数,表示最佳快餐店选址距离最远用户的距离。
注意:你的结果必须恰好有一位小数,小数位数不正确不得分。
Sample Input
1 4 2
1 3 2
2 4 1
Sample Output
HINT

数据范围
对于 10%的数据,N<=80,Li=1;
对于 30%的数据,N<=600,Li<=100;
对于 60% 的数据,N<=2000,Li<=10^9;
对于 100% 的数据,N<=10^5,Li<=10^9
正解:树形$DP+dfs$
解题报告:
首先我们要明确,直接求图的直径是错误的。
反例可以想想,大概就是在环上等距的三个点,然后其中一个点往外拓展了一棵树,由于我求出来之后按理要放在直径的中点上,但这种情况显然不满足。
下面我们需要考虑如何求一个点,使得它到图中的所有点的最大距离最小。
对于这种带了环的题目(又是基环外向树),我们一般是断掉环上的某一条边,再作考虑。
考虑断掉环上一条边,然后求树的直径的正确性,显然一条合法的路径肯定不能经过一整个环,那么就有一些部分是肯定不会经过的,我就可以枚举这些肯定不会经过的一条边,断掉,对于树与树之间肯定无影响,对环上的点,由于有两条路径,删掉不会导致“错过”最优答案。
断掉一条边之后变成一棵树,对于树而言求直径肯定就是对的了。
如果能快速地查询断掉这条边之后对得到的树的直径的查询就能得到答案。
我们先$dfs$一遍得到环上每个点拓展出去的树的直径,最终答案不会小于等于最大直径$/2$。
我们先人工地断开$1$到$cnt$(假设环长为$cnt$)的边,从前往后求一遍$u$,$v$:$u$表示的是$max(前缀中最大的一条链+当前节点的树的最大深度)$,$v$表示的是$max(前缀中两棵树的最大深度+这两个根节点直接的距离)$,后缀也做一遍,记为$u2,v2$。
那么我最后枚举断掉哪条边时,就可以快速合并了!
我们枚举断掉$i$到$i+1$这条边时,答案应该是$max(max(v[i],v2[i+1]),u[i]+u2[i+1]+1$到$cnt$的边权)。
公式的含义就是,前缀的一段的最大直径,后缀的一段的最大直径,加上,前缀和后缀的$u$经过$1$到$cnt$这条边之后组合起来的直径,三个取一个$max$即为答案。
我们显然需要使得这个最短。
最后我们需要和最大的树的直径取一个$max$,原因上面已经说了...
ps:话说这道题似乎线段树也可以做,不过复杂不少,而且细节很多,还多了一个$log$...
//It is made by ljh2000
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <string>
#include <complex>
using namespace std;
typedef long long LL;
const int MAXN = 100011;
const int MAXM = 200011;
int n,ecnt,first[MAXN],to[MAXM],next[MAXM],w[MAXM];
int b[MAXN],scnt,father[MAXN],val[MAXN],fa_w[MAXN];//val[i]表示环上第i个点到第i+1个点的距离
bool iscircle[MAXN],vis[MAXN];
LL f[MAXN],pre[MAXN],best[MAXN],pre2[MAXN],best2[MAXN],ans,chain; inline int getint(){
int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
} inline void dfs_find(int x,int fa){
vis[x]=1;
for(int i=first[x];i;i=next[i]) {
int v=to[i]; if(v==fa) continue;
if(vis[v]) {
if(iscircle[v]) continue;
int u=x;
while(u!=v) {
iscircle[u]=true;
b[++scnt]=u; val[scnt]=fa_w[u];
u=father[u];
}
iscircle[u]=true;
b[++scnt]=v; val[scnt]=w[i];
continue;
}
father[v]=x; fa_w[v]=w[i]; vis[v]=true;
dfs_find(v,x);
}
} inline void dfs(int x,int fa){
for(int i=first[x];i;i=next[i]) {
int v=to[i]; if(v==fa || iscircle[v]) continue;
dfs(v,x);
chain=max(chain,f[x]+f[v]+w[i]);
f[x]=max(f[x],f[v]+w[i]);
}
} inline void work(){
n=getint(); int x,y,z;
for(int i=1;i<=n;i++) {
x=getint(); y=getint(); z=getint();
next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; w[ecnt]=z;
next[++ecnt]=first[y]; first[y]=ecnt; to[ecnt]=x; w[ecnt]=z;
}
dfs_find(1,0); LL tot=0,da=0; int now;
for(int i=1;i<=scnt;i++) dfs(b[i],0);
for(int i=1;i<=scnt;i++) {
tot+=val[i-1];//环上权值前缀和
now=b[i];
pre[i]=max(pre[i-1],tot+f[now]);
best[i]=max(best[i-1],tot+da+f[now]);
da=max(da,f[now]-tot);//方便后面组合得到完整答案
}
tot=0; LL duan=val[scnt]; val[scnt]=da=0;
for(int i=scnt;i>=1;i--) {
tot+=val[i];
now=b[i];
pre2[i]=max(pre2[i+1],tot+f[now]);
best2[i]=max(best2[i+1],tot+da+f[now]);
da=max(da,f[now]-tot);
} ans=best[scnt]; LL choose;
for(int i=1;i<scnt;i++) {
choose=max(best[i],best2[i+1]);
choose=max(choose,pre[i]+pre2[i+1]+duan);
if(choose<ans) ans=choose;
}
ans=max(ans,chain);
if(ans&1) printf("%lld.5",ans>>1);
else printf("%lld.0",ans>>1);
} int main()
{
work();
return 0;
}
BZOJ3242/UOJ126 [Noi2013]快餐店的更多相关文章
- CF835F Roads in the Kingdom/UOJ126 NOI2013 快餐店 树的直径
传送门--CF 传送门--UOJ 题目要求基环树删掉环上的一条边得到的树的直径的最小值. 如果直接考虑删哪条边最优似乎不太可做,于是考虑另一种想法:枚举删掉的边并快速地求出当前的直径. 对于环上的点, ...
- bzoj 3242: [Noi2013]快餐店 章鱼图
3242: [Noi2013]快餐店 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 266 Solved: 140[Submit][Status] ...
- P1399 [NOI2013] 快餐店 方法记录
原题题面P1399 [NOI2013] 快餐店 题目描述 小 T 打算在城市 C 开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小 T 希望快餐店的地址选在离最 ...
- bzoj3242 [Noi2013]快餐店
Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...
- 【uoj126】 NOI2013—快餐店
http://uoj.ac/problem/126 (题目链接) 题意 求基环树直径. Solution zz选手迟早退役,唉,右转题解→_→:LCF 细节 拓扑排序的时候度数为0时入队.我在想什么w ...
- BZOJ3242 [Noi2013]快餐店 【环套树 + 单调队列dp】
题目链接 BZOJ3242 题解 题意很清楚,找一点使得最远点最近 如果是一棵树,就是直径中点 现在套上了一个环,我们把环单独拿出来 先求出环上每个点外向树直径更新答案,并同时求出环上每个点外向的最远 ...
- 3242: [Noi2013]快餐店 - BZOJ
Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...
- 动态规划:NOI2013 快餐店
Description 小 T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近 的地方. 快餐店的顾客分布 ...
- NOI2013 快餐店
http://uoj.ac/problem/126 总的来说,还是很容易想的,就是有点恶心. 首先,很明显只有一个环. 我们先找出这个环,给各棵树编号id[i],然后各棵树分别以环上的点为根,求出每个 ...
随机推荐
- 《从零开始学Swift》学习笔记(Day4)——用Playground工具编写Swift
Swift 2.0学习笔记(Day4)——用Playground工具编写Swift 原创文章,欢迎转载.转载请注明:关东升的博客 用Playground编写Swift代码目的是为了学习.测试算法.验证 ...
- Cocos2d-x Lua中多场景切换生命周期
在多个场景切换时候,场景的生命周期会更加复杂.这一节我们介绍一下场景切换生命周期.多个场景切换时候分为几种情况:情况1,使用pushScene函数从实现GameScene场景进入SettingScen ...
- HTTP headers with the Link header field HTTP协议支持分页(Pagination)操作,在Header中使用 Link 即可
RFC 5988 - Web Linking https://tools.ietf.org/html/rfc5988#section-5.1 https://www.zhihu.com/questi ...
- unity坑faq
遇到的坑记录下来,大都都是听说,没有实测 1. Graphics.copyTexture,在某些机型上不支持从不同类型拷贝 2. msaa 小米mix2不支持,晓龙845 3. android4.2下 ...
- Vue中使用定时器setInterval和setTimeout
js中定时器有两种,一个是循环执行setInterval,另一个是定时执行setTimeout 一.循环执行(setInterval) 顾名思义,循环执行就是设置一个时间间隔,每过一段时间都会执行一次 ...
- PyNest——part 2: populations of neurons
part 2: populations of neurons introduction 在这篇讲义中,我们着眼于创建和参数化神经元批次,并将它们连接起来. 当你完成这些材料时,你会知道如何: 创建具有 ...
- 2.6 基于ARDUINO UNO+MC20的路径显示功能
需要准备的硬件 MC20开发板 1个 https://item.taobao.com/item.htm?id=562661881042 GSM/GPRS天线 1根 https://item.taoba ...
- javascript高级语法二
一.BOM对象 1.什么是BOM对象? BOM是浏览器对象模型,核心对象就是window,所有浏览器都支持 window 对象.一个html文档对应一个window对象,主要功能是控制浏览器窗口的, ...
- Python基础(11)_python模块之time模块、rando模块、hashlib、os模块
一.模块 1.什么是模块:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀 模块的本质:模块的本质是一个py文件 2.模块分为三类:1)内置模块:2)第三方模块: ...
- str字符串、bool类型常用方法总结
字符串拼接 必须是字符串与字符串拼接 print('马化腾'+'马云') print('马化腾' * 10) 将打印10个马化腾 字符串翻转 [ : :-1] 字符串可以加和乘,不能减和乘 input ...