[Noi2013]快餐店
来源:互联网 发布:批量上传淘宝宝贝软件 编辑:程序博客网 时间:2024/04/29 13:12
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
2.0
题解:
首先可以发现这是一个环套树,要求离最远用户的距离最短,那么这个快餐店一定在某一条路的中点。
两种情况:
1.这条路在环外面,那么答案就是直径>>1
2、这条路经过环,考虑从环上断开一条边,因为ans不可能经过一整个环。所以我们枚举断开的路径,求其最长路径。
断开某一条边的答案可以DP求
给环上的点标号1~k
u1[i]树上1~i到1的最短路,u2[i]树上i~k到k的最短路
v1[i]表示1~i的任意两棵树之间组成的最长链的最大值,v2[i]类似,表示的是i~k
最终ans就为:max(max(v1[i],v2[i+1]),u1[i]+u2[i+1]+(1~k的值))
#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<iostream>#define ll long longusing namespace std;const int N=100005;struct node{int y,z,next;}sa[N*2];int len=0,first[N];int n; void ins(int x,int y,int z){len++;sa[len].y=y;sa[len].z=z;sa[len].next=first[x];first[x]=len;}int fa[N],pos[N],cnt=0,a[N],b[N],c[N],dfn=0;bool tf[N];void dfs(int x){pos[x]=++dfn;for(int i=first[x];i!=-1;i=sa[i].next){int y=sa[i].y;if(fa[x]!=y){if(!pos[y]){fa[y]=x;c[y]=sa[i].z;dfs(y);}else if(pos[y]>pos[x]){for(;y!=x;y=fa[y]){tf[y]=0;a[++cnt]=y;b[cnt]=c[y];}tf[x]=0;a[++cnt]=x;b[cnt]=sa[i].z;}}}}ll f[N];//以i为起点的最长路径ll ans=0;void DP(int x,int last){for(int i=first[x];i!=-1;i=sa[i].next){int y=sa[i].y;if(tf[y]&&y!=last){DP(y,x); ans=max(ans,f[x]+f[y]+sa[i].z);f[x]=max(f[x],f[y]+sa[i].z);}}}ll u1[N],u2[N],v1[N],v2[N];//树上1~i到1的最短路,树上i~k到k的最短路//表示1~i的任意两棵树之间组成的最长链的最大值,v2[i]类似,表示的是i~k int main(){scanf("%d",&n);memset(first,-1,sizeof(first));memset(tf,1,sizeof(tf));int x,y,z;for(int i=1;i<=n;i++){scanf("%d%d%d",&x,&y,&z);ins(x,y,z);ins(y,x,z);}int i;dfs(1); ll sum=0,mx=0; for (i=1; i<=cnt; i++) DP(a[i],0); for (i=1; i<=cnt; i++){ sum+=b[i-1]; u1[i]=max(u1[i-1],f[a[i]]+sum); v1[i]=max(v1[i-1],f[a[i]]+sum+mx); mx=max(mx,f[a[i]]-sum); } ll tmp=b[cnt]; sum=mx=b[cnt]=0; for (i=cnt; i; i--){ sum+=b[i]; u2[i]=max(u2[i+1],f[a[i]]+sum); v2[i]=max(v2[i+1],f[a[i]]+sum+mx); mx=max(mx,f[a[i]]-sum); } ll mn=v1[cnt]; for (i=1; i<cnt; i++) mn=min(mn,max(max(v1[i],v2[i+1]),u1[i]+u2[i+1]+tmp)); ans=max(ans,mn); printf("%lld.%d\n",ans>>1,(ans&1)?5:0); return 0; }/*41 2 11 4 21 3 22 4 1*/
- NOI2013 快餐店
- [Noi2013]快餐店
- BZOJ3242: [Noi2013]快餐店
- bzoj3242: [Noi2013]快餐店
- 3242: [Noi2013]快餐店
- NOI2013快餐店【图上找环+线段树】
- 【树DP+基环树】[NOI2013]快餐店
- [BZOJ3242][Noi2013]快餐店 && 环套树+线段树
- bzoj3242: [Noi2013]快餐店 树形dp+线段树
- bzoj 3242: [Noi2013]快餐店 dfs&递推
- [BZOJ3242][NOI2013]快餐店-基环树-动态规划
- [BZOJ3242][Noi2013]快餐店(树形dp+线段树)
- [线段树优化 DP] BZOJ 3242 [Noi2013]快餐店
- 3066 快餐店
- NOI2013行纪
- NOI2013 书法家
- 上海快餐店一览
- 《DOS快餐店》笔记
- php中self与static的区别
- 关于IIC和SPI总线
- 异步通知
- python下批量修改图片格式和大小
- 静态局部变量
- [Noi2013]快餐店
- java注解,@,注解有什么用
- Java String Source Code
- ubuntu下修复不能访问分区问题
- 图的储存
- HDU 2955 Robberies【01背包】
- 技术文章 | JAVASCRIPT作为功能编程介绍
- Linux学习之路
- Maven学习总结(八)——使用Maven构建多模块项目