传送门

基环树的题当然先考虑树上怎么搞,直接求个直径就完事了

现在多了个环,先把非环上的直径(设为 $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]快餐店的更多相关文章

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

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

  2. luogu P1399 [NOI2013]快餐店

    传送门 注意到答案为这个基环树直径\(/2\) 因为是基环树,所以考虑把环拎出来.如果直径不过环上的边,那么可以在环上每个点下挂的子树内\(dfs\)求得.然后如果过环上的边,那么环上的部分也是一条链 ...

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

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

  4. bzoj3242 [Noi2013]快餐店

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

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

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

  6. 动态规划:NOI2013 快餐店

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

  7. NOI2013 快餐店

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

  8. bzoj 3242: [Noi2013]快餐店

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

  9. BZOJ3242/UOJ126 [Noi2013]快餐店

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

随机推荐

  1. 利用pdfbox和poi抽取pdf、doc以及docx格式的内容

    使用pdfbox1.5.0抽取pdf格式文档内容,使用poi3.7抽取doc及docx文档内容: /** * Created by yan.shi on 2017/9/25. */ import or ...

  2. git多人参与的项目 -> 分支代码如何合并到主干

    个人理解:合并分支时候就是当前分支,与别的分支先合并一遍,然后解决分支中存在的所有冲突,之后将本地分支代码提交到git远程仓库,之后切换主干分支 ,将主干分支与分支内容合并,解决冲突, 在提交主干分支 ...

  3. HashMap如何实现序列化

    /** * Save the state of the <tt>HashMap</tt> instance to a stream (i.e., * serialize it) ...

  4. 191022Django模板

    一.变量和句点符深度查找 字符串变量引用 def show_time(request): now_time = datetime.datetime.now() return render(reques ...

  5. 190707Python-MySQL

    一.Python连接MySQL import pymysql conn = pymysql.connect(host='192.168.100.4', port=3306, user='dongfei ...

  6. 黑马lavarel教程---4、csrf验证及相关

    黑马lavarel教程---4.csrf验证及相关 一.总结 一句话总结: csrf验证就像短信验证码那样验证用户身份,这个验证是为了验证是本站的操作,用的是一个token字符串,外站如果有了这个to ...

  7. 导入 kotlin(7)

    导入包 除了默认导入之外,每个文件可以包含它自己的导入指令. 导入语法在语法中讲述.可以导入一个单独的名字,如.import foo.Bar // 现在 Bar 可以不用限定符访问也可以导入一个作用域 ...

  8. 运算 Kotlin(3)

    运算Kotlin支持数字运算的标准集,运算被定义为相应的类成员(但编译器会将函数调用优化为相应的指令) . 参见运算符重载.对于位运算,没有特殊字符来表示,而只可用中缀方式调用命名函数,例如:val ...

  9. Android Studio安装Unable to access Android SDK add-on list处理方法

    Unable to access Android SDK add-on list. 很多人写的加屏蔽语句,跳过检测,其实是不行的,因为最后还是要下载. 不翻墙的情况下,一般都是修改host文件:C:\ ...

  10. 关于在IDEA中使用maven projects 的Lifecycle中打包package报expected START_TAG or END_TAG not TEXT

    报错指定到maven本地仓库下的settings.xml某一行,如下列JDK配置: <profiles> <profile>    <id>jdk-1.8</ ...