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/ ...
随机推荐
- AtCoder AGC036C GP 2 (组合计数)
题目链接 https://atcoder.jp/contests/agc036/tasks/agc036_c 题解 终于有时间补agc036的题了. 这题其实不难的来着--我太菜了考场上没想出来 首先 ...
- ACM技能表
看看就好了(滑稽) 数据结构 栈 栈 单调栈 队列 一般队列 优先队列/单调队列 循环队列 双端队列 链表 一般链表 循环链表 双向链表 块状链表 十字链表 邻接表/邻接矩阵 邻接表 邻接多重表 Ha ...
- 使用jQuery创建可删除添加行的动态表格,超级简单实用的方法
使用jQuery动态的添加和删除表格里面的行,不多说了直接上代码. <!DOCTYPE html> <html> <head> <meta charset=& ...
- 2019年9月17 发布 Java 13
Java 13 明天发布,最新最全新特性解读 2017年8月,JCP执行委员会提出将Java的发布频率改为每六个月一次,新的发布周期严格遵循时间点,将在每年的3月份和9月份发布. 目前,JDK官网 ...
- C++入门经典-例5.3例5.4-输出int指针运算后的地址值
1:代码如下: // 5.3.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> using ...
- leetcode-easy-math-412 Fizz Buzz
mycode 99.06% class Solution(object): def fizzBuzz(self, n): """ :type n: int :rtype ...
- shell初级-----处理用户输入
命令行参数 读取参数 位置参数变量是标准的数字:$0是程序名,$1是第一个参数,$2,是第二个参数,直到第九个参数$9. 特殊的变量:$#表示参数个数,$?表示最后运行的命令的结束代码(返回值) 每个 ...
- day2_Python基础二
一.格式化输出 1.%s or %d %:表示占位符,注意,需要在内容中显示%时,在他之前增加一个%来转义,如显示5%,则:5%% s:表示字符串 d:表示数值digital 例子: name = i ...
- MPP - GreenPlum数据库安装以及简单使用
一.集群介绍 共3台主机,ip 为193.168.0.93 193.168.0.94 193.168.0.95 集群对应master和segment如下,193.168.0.93为master节 ...
- dvm 的进程和 Linux 的进程, 应用程序的进程是否为同一个概念?
dvm 指 dalvik 的虚拟机. 每一个 Android 应用程序都拥有一个独立的 Dalvik 虚拟机实例,应用程序都在它自己的进程中运行.而每一个 dvm 都是在 Linux 中的一个进程,所 ...