bzoj3242 [Noi2013]快餐店
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$。
这应该是$NOI2013$最水的一道题吧。。不过我还是写了$3$个小时,因为漏了一个情况,结果还有$95$分。。
很显然,直接求直径是错的,样例$2$就已经告诉你了。那么我们可以发现,这题其实是要求断掉环上一条边的直径,且使得这个直径最小。
我们先在环上随便找一个点作为根,然后$dfs$。先把所有树的情况处理完,这样对于每个点,$f[x]$表示$x$到它子树的最长链,用树形$dp$先搞一下就行了。
然后考虑环上怎么做。枚举断哪条边,然后我们可以记一个前缀最大值和一个后缀最大值。$v1[x]$表示环顶到$x$逆时针,$f[x]+dis(rt,x)$的最大值($rt$即为环顶),$v2[x]$表示环顶到$x$顺时针,$f[x]+dis(rt,x)$的最大值。注意,两个$dis$是不一样的,一个是逆时针的$dis$,另一个是顺时针的。
这样,我们枚举断边,假设我们断掉的是$x->x+1$这条边,那么断这条边的直径就是$f[rt]+max(v1[x],v2[x+1])$和$v1[x]+v2[x+1]$的最大值(注意此时的$f[rt]$可能已经被别的链更新了,所以必须加上)。然后我们对于所有的最大值,取一个最小值即可。
然后这就是我开始的$95$分算法,还有一种情况没有考虑到。。
注意到上面的情况,我们可以发现它算的是环上两点距离和它们子树的最长链,但是这两点是位于断边两侧的,也就是说,断边同侧的两点同样有可能构成直径。
那么如何计算同侧的情况呢?我们设$v1[x]$为环顶到$x$逆时针,$f[x]-dis(rt,x)$的最大值,$v2[x]$为环顶到$x$顺时针,$f[x]-dis(rt,x)$的最大值。那么这时,枚举断边$i->i+1$,答案有可能由$f[x]+dis(rt,x)-v1[x-1]$和$f[x+1]+dis(rt,x+1)-v2[x+2]$的最大值构成,注意到多余部分的$dis$一加一减,正好被抵消了,所以我们是不会算错的。我们算出这两个值以及上面两个值,取一个最大值,再对所有的最大值取一个最小值,就是答案了。
//It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1LL<<60)
#define N (500010)
#define il inline
#define RG register
#define ll long long
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) using namespace std; struct edge{ int nt,to; ll dis; }g[*N]; int head[N],fa[N],dfn[N],low[N],st[N],n,rt,num,cnt;
ll dis[N],f[N],d[N],v1[N],v2[N],u1[N],u2[N],ans; il int gi(){
RG int x=,q=; RG char ch=getchar();
while ((ch<'' || ch>'') && ch!='-') ch=getchar();
if (ch=='-') q=-,ch=getchar();
while (ch>='' && ch<='') x=x*+ch-,ch=getchar();
return q*x;
} il void insert(RG int from,RG int to,RG ll dis){
g[++num]=(edge){head[from],to,dis},head[from]=num; return;
} il void circle(RG int rt,RG int x,RG ll len){
RG int top=,tp=; RG ll D=len,res=inf,res1,res2;
for (RG int i=x;i!=rt;i=fa[i]) ++tp,D+=dis[i]; top=tp;
for (RG int i=x;i!=rt;i=fa[i]) st[tp--]=i; st[]=rt;
for (RG int i=;i<=top;++i){
d[i]=d[i-]+dis[st[i]];
v1[i]=max(v1[i-],f[st[i]]+d[i]);
u1[i]=max(u1[i-],f[st[i]]-d[i]);
}
for (RG int i=top;i>;--i){
v2[i]=max(v2[i+],f[st[i]]+D-d[i]);
u2[i]=max(u2[i+],f[st[i]]-D+d[i]);
}
for (RG int i=;i<top-;++i){
res1=max(v1[i]+v2[i+],f[rt]+max(v1[i],v2[i+]));
res2=max(f[st[i]]+d[i]+u1[i-],f[st[i+]]+D-d[i+]+u2[i+]);
res=min(res,max(res1,res2));
}
res=min(res,f[rt]+v1[top]),res=min(res,f[rt]+v2[]),ans=max(ans,res); return;
} il void tarjan0(RG int x,RG int p){
fa[x]=p,dfn[x]=low[x]=++cnt; RG int v;
for (RG int i=head[x];i;i=g[i].nt){
v=g[i].to; if (v==p) continue;
if (!dfn[v]){
dis[v]=g[i].dis,tarjan0(v,x);
low[x]=min(low[x],low[v]);
} else low[x]=min(low[x],dfn[v]);
}
for (RG int i=head[x];i;i=g[i].nt){
v=g[i].to; if (v==p) continue;
if (fa[v]!=x && dfn[x]<dfn[v]) rt=x;
}
return;
} il void tarjan(RG int x,RG int p){
fa[x]=p,dfn[x]=low[x]=++cnt; RG int v;
for (RG int i=head[x];i;i=g[i].nt){
v=g[i].to; if (v==p) continue;
if (!dfn[v]){
dis[v]=g[i].dis,tarjan(v,x);
low[x]=min(low[x],low[v]);
} else low[x]=min(low[x],dfn[v]);
if (dfn[x]<low[v]){
ans=max(ans,f[x]+f[v]+g[i].dis);
f[x]=max(f[x],f[v]+g[i].dis);
}
}
for (RG int i=head[x];i;i=g[i].nt){
v=g[i].to; if (v==p) continue;
if (fa[v]!=x && dfn[x]<dfn[v]) circle(x,v,g[i].dis);
}
return;
} il void work(){
n=gi();
for (RG int i=,u,v,w;i<=n;++i) u=gi(),v=gi(),w=gi(),insert(u,v,w),insert(v,u,w);
tarjan0(,); for (RG int i=;i<=n;++i) dfn[i]=low[i]=fa[i]=dis[i]=;
cnt=,tarjan(rt,); printf("%0.1Lf",0.5*(long double)ans); return;
} int main(){
File("foodshop");
work();
return ;
}
bzoj3242 [Noi2013]快餐店的更多相关文章
- BZOJ3242 [Noi2013]快餐店 【环套树 + 单调队列dp】
题目链接 BZOJ3242 题解 题意很清楚,找一点使得最远点最近 如果是一棵树,就是直径中点 现在套上了一个环,我们把环单独拿出来 先求出环上每个点外向树直径更新答案,并同时求出环上每个点外向的最远 ...
- 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/UOJ126 [Noi2013]快餐店
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- 3242: [Noi2013]快餐店 - BZOJ
Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...
- 动态规划:NOI2013 快餐店
Description 小 T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近 的地方. 快餐店的顾客分布 ...
- NOI2013 快餐店
http://uoj.ac/problem/126 总的来说,还是很容易想的,就是有点恶心. 首先,很明显只有一个环. 我们先找出这个环,给各棵树编号id[i],然后各棵树分别以环上的点为根,求出每个 ...
- bzoj 3242: [Noi2013]快餐店
Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...
- CF835F Roads in the Kingdom/UOJ126 NOI2013 快餐店 树的直径
传送门--CF 传送门--UOJ 题目要求基环树删掉环上的一条边得到的树的直径的最小值. 如果直接考虑删哪条边最优似乎不太可做,于是考虑另一种想法:枚举删掉的边并快速地求出当前的直径. 对于环上的点, ...
随机推荐
- AIM Tech Round 5 (rated, Div. 1 + Div. 2) D(SET,思维)
#include<bits/stdc++.h>using namespace std;const long long mod = 1e9+7;char s[370007][27];long ...
- centos 通过yum安装GlusterFS
1.环境 centos 6.5 64 bit glusterfs-3.5 2.配置yum源 http://download.gluster.org/pub/gluster/glusterfs/repo ...
- uoj #5. 【NOI2014】动物园
#5. [NOI2014]动物园 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的园长决定开设算法班,让 ...
- 使用idrac远程管理卡操作安装Centos
浏览器打开远程管理网卡地址(浏览器建议用IE,本次用的IE11,其他浏览器可能不能用) 1.首先设置虚拟控制台插件类型(推荐该为本地) 点击启动后,可能会弹窗,选择允许 2.添加镜像 创建虚拟介质 连 ...
- ELK(+Redis)-开源实时日志分析平台
################################################################################################### ...
- 退役or延期退役
究竟是\(150\)天后退役,还是能继续续命呢? 一切看自己了!加油!\(cyh\)!千万不要败在别人的只言片语之下啊!
- jmeter如何设置全局变量以及调用方法
当遇到如跨线程组调用变量等情况,需要设置全局变量. 1.打开函数助手 输入需要的值然后点击生成按钮,或者直接使用${__setProperty(newuserid,${userid},)}的格式 设置 ...
- CF213E Two Permutations 线段树维护哈希值
当初竟然看成子串了$qwq$,不过老师的$ppt$也错了$qwq$ 由于子序列一定是的排列,所以考虑插入$1$到$m$到$n-m+1$到$n$; 如何判断呢?可以用哈希$qwq$: 我们用线段树维护哈 ...
- ThreadFactory 线程池工厂
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Thr ...
- Hive_hdfs csv导入hive demo
1 create csv file.student.csv 4,Rose,M,78,77,76 5,Mike,F,99,98,98 2 put it to hdfs. # hdfs dfs -put ...