P1399 [NOI2013]快餐店
基环树的题当然先考虑树上怎么搞,直接求个直径就完事了
现在多了个环,先把非环上的直径(设为 $ans$)和环上节点 $x$ 到叶子的最大距离(设为 $dis[x]$)求出来
考虑到对于某种最优的方案,环上一定有某条边完全不用走
所以可以枚举断哪个边然后暴力,显然会 $T$ 飞
考虑能够快速求出某条边断开后经过环的最大直径
预处理 $A[i],B[i],C[i],D[i]$
$A[i]$ 表示从环上某个固定的起点出发到达 $i$ 之前(包括 $i$) 的最长路径长度(这里路径包括到达叶子节点的路径)
这个可以通过维护起点到当前距离再加上我们之前求出的 $dis$ 得到
$B[i]$ 表示从环上那个固定的起点出发到达 $i$ 之前(包括 $i$)的节点中某两个叶子节点之间的最长距离
这个即为 $sum[i]-sum[j]+dis[i]+dis[j]$,其中 $sum[i]$ 表示起点到 $i$ 的环上路程
移项 $sum[i]+dis[i]+dis[j]-sum[j]$ ,动态维护当前 $dis[j]-sum[j]$ 的最大值即可
$C[i]$ 表示从环上终点(其实就是那个固定的起点的另一边的第一个节点)出发......(剩下的和 $A[i]$表示的是一样的)
$D[i]$ 同 $B[i]$ ,只是起点变成了终点,反过来了
那么预处理之后,枚举断边 $i$ (注意边 $i$ 连接 $i$ 和 $i+1$)那么 $t=max(B[i],D[i+1],A[i]+C[i+1]+w)$
其中 $w$ 是连接起点和终点的边的长度,那么 $A[i]+C[i+1]+w$ 其实就是跨过起点终点的距离
最后 $ans=max(ans,min(t))$,注意 $t$ 取最小值,因为断边是在最优方案下,肯定要取最小
- #include<iostream>
- #include<cstdio>
- #include<algorithm>
- #include<cstring>
- #include<cmath>
- #include<vector>
- using namespace std;
- typedef long long ll;
- inline int read()
- {
- int x=,f=; char ch=getchar();
- while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
- while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
- return x*f;
- }
- const int N=2e5+;
- const ll INF=1e18;
- int n;
- int fir[N],from[N<<],to[N<<],val[N<<],cntt;
- inline void add(int a,int b,int c) { from[++cntt]=fir[a]; fir[a]=cntt; to[cntt]=b; val[cntt]=c; }
- bool vis[N],ring[N],GG;
- vector <int> st,wt;
- vector <int> q,w;
- void find(int x,int fa,int ww)
- {
- st.push_back(x); wt.push_back(ww); vis[x]=;
- for(int i=fir[x];i;i=from[i])
- {
- int &v=to[i]; if(v==fa) continue;
- if(vis[v])
- {
- while(st[st.size()-]!=v)
- {
- ring[st[st.size()-]]=;
- q.push_back(st[st.size()-]);
- w.push_back(wt[wt.size()-]);
- st.pop_back(); wt.pop_back();
- }
- ring[v]=GG=; q.push_back(v);
- w.push_back(val[i]); return;
- }
- find(v,x,val[i]); if(GG) return;
- }
- st.pop_back(); wt.pop_back();
- }
- ll dis[N],ans;
- void dfs(int x,int fa)
- {
- for(int i=fir[x];i;i=from[i])
- {
- int &v=to[i]; if(ring[v]||v==fa) continue;
- dfs(v,x); ans=max(ans,dis[x]+dis[v]+val[i]);
- dis[x]=max(dis[x],dis[v]+val[i]);
- }
- }
- ll A[N],B[N],C[N],D[N];
- void solve()
- {
- find(,,); for(auto u: q) dfs(u,u);
- ll sum=,mx=; int len=q.size();
- A[]=B[]=dis[q[]];
- for(int i=;i<len;i++)
- {
- mx=max(mx,dis[q[i-]]-sum); sum+=w[i-];
- A[i]=max(A[i-],sum+dis[q[i]]);
- B[i]=max(B[i-],mx+sum+dis[q[i]]);
- }
- sum=mx=; C[len-]=D[len-]=dis[q[len-]];
- for(int i=len-;i>=;i--)
- {
- mx=max(mx,dis[q[i+]]-sum); sum+=w[i];
- C[i]=max(C[i+],sum+dis[q[i]]);
- D[i]=max(D[i+],mx+sum+dis[q[i]]);
- }
- ll res=B[len-];
- for(int i=;i<len-;i++)
- {
- ll t=max(max(B[i],D[i+]), A[i]+C[i+]+w[len-] );
- res=min(res,t);
- }
- ans=max(ans,res);
- printf("%lld",ans>>);
- ans& ? printf(".5\n") : printf(".0\n");
- }
- int main()
- {
- n=read(); int a,b,c;
- for(int i=;i<=n;i++)
- {
- a=read(),b=read(),c=read();
- add(a,b,c); add(b,a,c);
- }
- solve();
- return ;
- }
P1399 [NOI2013]快餐店的更多相关文章
- P1399 [NOI2013] 快餐店 方法记录
原题题面P1399 [NOI2013] 快餐店 题目描述 小 T 打算在城市 C 开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小 T 希望快餐店的地址选在离最 ...
- luogu P1399 [NOI2013]快餐店
传送门 注意到答案为这个基环树直径\(/2\) 因为是基环树,所以考虑把环拎出来.如果直径不过环上的边,那么可以在环上每个点下挂的子树内\(dfs\)求得.然后如果过环上的边,那么环上的部分也是一条链 ...
- bzoj 3242: [Noi2013]快餐店 章鱼图
3242: [Noi2013]快餐店 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 266 Solved: 140[Submit][Status] ...
- bzoj3242 [Noi2013]快餐店
Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...
- 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希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...
- BZOJ3242/UOJ126 [Noi2013]快餐店
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
随机推荐
- Intelij IDEA创建SpringBoot项目 - 配置文件的解释
springboot介绍 官网:spring.io Spring Boot is designed to get you up and running as quickly as possible, ...
- 如何求ArrayList集合的交集 并集 差集 去重复并集
需要用到List接口中定义的几个方法: addAll(Collection<? extends E> c) :按指定集合的Iterator返回的顺序将指定集合中的所有元素追加到此列表的末尾 ...
- 关于MySQL中查询结果的count和from后的条件与where后的条件对比
啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦 ...
- RF-创建一个自定义关键字库
仓库自定义库 这里以Selenium2Library库进行举例说明: 编写一个自定义仓库类(与库文件夹名一致),继承关键字类,指定范围和版本即可. 需要声明__init__. import os fr ...
- LinkedList,ArrayList,Vector,HashMap,HashSet,HashTable之间的区别与联系
在编写java程序中,我们最常用的除了八种基本数据类型,String对象外还有一个集合类,在我们的的程序中到处充斥着集合类的身影!java中集合大家族的成员实在是太丰富了,有常用的ArrayList. ...
- 浏览器端-W3School-HTML:HTML DOM Style 对象
ylbtech-浏览器端-W3School-HTML:HTML DOM Style 对象 1.返回顶部 1. HTML DOM Style 对象 Style 对象 Style 对象代表一个单独的样式声 ...
- SweetAlert(弹出层插件)
怀着非常.非常恼火的心情写下这个博文.我深深怀疑有一些人只会瞎粘贴复制别人的博文,自己试都不试就发布到网上,左右看的人想法,就此深通恶绝!! 废话不多说. SweetAlert是一个简洁好用的自制Al ...
- Selenium 2自动化测试实战17(警告框处理)
一.警告框处理 在WebDriver中处理JavaScript所生成的alert.confirm以及prompt十分简单,只需要使用switch_to_alert()方法定位到alert/confir ...
- 阶段3 2.Spring_01.Spring框架简介_04.spring发展历程
- SQL Server 批量创建作业(备份主分区)
一. 需求背景 在我的数据库实例中,有很多类似下图所示的数据库,这些数据库的名称是有规律的,每个数据库包含的表都是相同的,其中2个表是类似流水记录的表,表的数据量会比较大,占用的空间有几十G到上百G不 ...