本文版权归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 2 1
1 4 2
1 3 2
2 4 1

Sample Output

2.0

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]快餐店的更多相关文章

  1. CF835F Roads in the Kingdom/UOJ126 NOI2013 快餐店 树的直径

    传送门--CF 传送门--UOJ 题目要求基环树删掉环上的一条边得到的树的直径的最小值. 如果直接考虑删哪条边最优似乎不太可做,于是考虑另一种想法:枚举删掉的边并快速地求出当前的直径. 对于环上的点, ...

  2. bzoj 3242: [Noi2013]快餐店 章鱼图

    3242: [Noi2013]快餐店 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 266  Solved: 140[Submit][Status] ...

  3. P1399 [NOI2013] 快餐店 方法记录

    原题题面P1399 [NOI2013] 快餐店 题目描述 小 T 打算在城市 C 开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小 T 希望快餐店的地址选在离最 ...

  4. bzoj3242 [Noi2013]快餐店

    Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...

  5. 【uoj126】 NOI2013—快餐店

    http://uoj.ac/problem/126 (题目链接) 题意 求基环树直径. Solution zz选手迟早退役,唉,右转题解→_→:LCF 细节 拓扑排序的时候度数为0时入队.我在想什么w ...

  6. BZOJ3242 [Noi2013]快餐店 【环套树 + 单调队列dp】

    题目链接 BZOJ3242 题解 题意很清楚,找一点使得最远点最近 如果是一棵树,就是直径中点 现在套上了一个环,我们把环单独拿出来 先求出环上每个点外向树直径更新答案,并同时求出环上每个点外向的最远 ...

  7. 3242: [Noi2013]快餐店 - BZOJ

    Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...

  8. 动态规划:NOI2013 快餐店

    Description 小 T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近 的地方. 快餐店的顾客分布 ...

  9. NOI2013 快餐店

    http://uoj.ac/problem/126 总的来说,还是很容易想的,就是有点恶心. 首先,很明显只有一个环. 我们先找出这个环,给各棵树编号id[i],然后各棵树分别以环上的点为根,求出每个 ...

随机推荐

  1. 《从零开始学Swift》学习笔记(Day 22)——闭包那些事儿!

    原创文章,欢迎转载.转载请注明:关东升的博客    我给Swift 中的闭包一个定义:闭包是自包含的匿名函数代码块,可以作为表达式.函数参数和函数返回值,闭包表达式的运算结果是一种函数类型. Swif ...

  2. 《从零开始学Swift》学习笔记(Day 7)——Swift 2.0中的print函数几种重载形式

    原创文章,欢迎转载.转载请注明:关东升的博客 Swift 2.0中的print函数有4种重载形式: l   print(_:).输出变量或常量到控制台,并且换行. l   print(_:_:).输出 ...

  3. XSL-FO Page Layout

    Simple Layout Let's take a look at the simple page layout that we saw earlier in the course. The sim ...

  4. 如何在Pycharm设置ES6语法环境

    首先 如果不进行相关设置就刚ES6 语法的话,会出现下面提示性错误(运行还是能正常出效果的): (let 飘红, 这只是其中之一, 其他语法也会飘红) 接着,就是解决问题: 首先打开设置: 接着找到下 ...

  5. “格式化HDFS后,HMaster进程启动失败”的问题解决

    用 hadoop namenode -fromat 格式化后,用./start-hbase.sh 启动HMaster和HRegionServer,但是过几秒种后HMaster进程自动关闭,HRegio ...

  6. Kafka高可用的保证

    zookeeper作为去中心化的集群模式,消费者需要知道现在那些生产者(对于消费者而言,kafka就是生产者)是可用的.    如果没有zookeeper每次消费者在消费之前都去尝试连接生产者测试下是 ...

  7. Python学习笔记2_Python基础

    一.变量(给数据起个名字) 变量是计算机内存中的一块区域,变量可以存储规定范围内的值,而且值可以改变. 1.变量的命名方法 -变量名有字母.数字.下划线组成 -不能以数字开头 -不可以使用关键字 -a ...

  8. 1.7 使用电脑测试MC20的发送带中文的短信功能

    需要准备的硬件 MC20开发板 1个 https://item.taobao.com/item.htm?id=562661881042 GSM/GPRS天线 1根 https://item.taoba ...

  9. PyQt4 进度条和日历 代码

    # -*- coding: utf-8 -*- """ ------------------------------------------------- File Na ...

  10. bootstrap模板

    一.bootstrap基本介绍 1.什么是bootstrap? bootstrap就是个前端快速开发的工具,该工具是个简单.直观.强悍的前端开发框架,让web开发更加迅速简单,同时也是个响应式布局,兼 ...