3242: [Noi2013]快餐店

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 266  Solved: 140
[Submit][Status]

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 2 1
1 4 2
1 3 2
2 4 1

Sample Output

2.0

HINT

数据范围

对于 10%的数据,N<=80,Li=1;

对于 30%的数据,N<=600,Li<=100;

对于 60% 的数据,N<=2000,Li<=10^9;

对于 100% 的数据,N<=10^5,Li<=10^9

  枚举环上所有边,删掉边转化成树球直径。

  另,用stack实现dfs不能直接改造成tarjan

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 110000
#define MAXV MAXN*2
#define MAXE MAXV*2
#define INF 0x3f3f3f3f3f3f3f3fLL
#define MAXT MAXN*4
#define lch (now<<1)
#define rch (now<<1^1)
#define smid ((sgt[now].l+sgt[now].r)>>1)
typedef long long qword;
struct sgt_node
{
int l,r;
pair<qword,int> r1,r2;
}sgt[MAXT];
qword val1[MAXN];
qword val2[MAXN];
void Build_sgt(int now,int l,int r)
{
sgt[now].l=l;sgt[now].r=r;
if (l==r)
{
sgt[now].r1.first=val1[l];
sgt[now].r1.second=l;
sgt[now].r2.first=val2[l];
sgt[now].r2.second=l;
return ;
}
Build_sgt(lch,l,smid);
Build_sgt(rch,smid+,r);
sgt[now].r1=max(sgt[lch].r1,sgt[rch].r1);
sgt[now].r2=max(sgt[lch].r2,sgt[rch].r2);
}
pair<qword,int> Query_sgt1(int now,int l,int r)
{
if (l>r)return make_pair(-INF,-);
if (l==sgt[now].l && r==sgt[now].r)
return sgt[now].r1;
if (r<=smid)
return Query_sgt1(lch,l,r);
else if (l>smid)
return Query_sgt1(rch,l,r);
else
return max(Query_sgt1(lch,l,smid),Query_sgt1(rch,smid+,r));
}
pair<qword,int> Query_sgt2(int now,int l,int r)
{
if (l>r)return make_pair(-INF,-);
if (l==sgt[now].l && r==sgt[now].r)
return sgt[now].r2;
if (r<=smid)
return Query_sgt2(lch,l,r);
else if (l>smid)
return Query_sgt2(rch,l,r);
else
return max(Query_sgt2(lch,l,smid),Query_sgt2(rch,smid+,r));
} struct Edge
{
int np;
qword val1;
Edge *next,*neg;
}E[MAXE],*V[MAXV];
int tope=-;
void addedge(int x,int y,qword z)
{
E[++tope].np=y;
E[tope].val1=z;
E[tope].next=V[x];
V[x]=&E[tope];
}
int pnt[MAXN];
int vis[MAXN];
int stack[MAXV],tops=-;
qword rdis[MAXN];
qword pdis[MAXN];
int dfn[MAXN],dfstime;
int chead,ctail;
qword clen; void dfs(int now)
{
Edge *ne;
dfn[now]=++dfstime;
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==pnt[now])continue;
if (dfn[ne->np])
{
if (dfn[ne->np]<dfn[now])
{
ctail=now;
chead=ne->np;
clen=ne->val1+rdis[now]-rdis[ne->np];
}
continue;
}
rdis[ne->np]=rdis[now]+ne->val1;
pdis[ne->np]=ne->val1;
pnt[ne->np]=now;
dfs(ne->np);
}
}
qword tdis[MAXN];
int pnt2[MAXN];
qword dfs2(int now,int p,qword d)
{
qword mxdpth=d;
Edge *ne;
stack[++tops]=now;
pnt2[now]=p;
tdis[now]=d;
while(~tops)
{
now=stack[tops--];
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==pnt2[now])continue;
pnt2[ne->np]=now;
tdis[ne->np]=tdis[now]+ne->val1;
mxdpth=max(mxdpth,tdis[now]+ne->val1);
stack[++tops]=ne->np;
}
}
return mxdpth;
}
qword dist[MAXV];
int pntt[MAXV];
qword dfs3(int now,int x1,int x2)
{
Edge *ne;
stack[++tops]=now;
dist[now]=;
pntt[now]=now;
qword mxdis=;
int mxid=now;
while (~tops)
{
now=stack[tops--];
if (mxdis<dist[now])
mxdis=dist[now],mxid=now;
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==pntt[now] || ne->np==x1 || ne->np==x2)continue;
dist[ne->np]=dist[now]+ne->val1;
pntt[ne->np]=now;
stack[++tops]=ne->np;
}
}
now=mxid;
mxdis=;
pntt[now]=now;
stack[++tops]=now;
dist[now]=;
while (~tops)
{
now=stack[tops--];
if (mxdis<dist[now])
mxdis=dist[now],mxid=now;
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==pntt[now] || ne->np==x1 || ne->np==x2)continue;
dist[ne->np]=dist[now]+ne->val1;
pntt[ne->np]=now;
stack[++tops]=ne->np;
}
}
return mxdis;
}
qword seq0[MAXN];
qword seq[MAXN];
qword prvdis0[MAXN];
qword prvdis[MAXN];
int que[MAXN];
qword qres2[MAXN];
qword qres3[MAXN];
void solve1(int m)
{
int head=,tail=-;
prvdis[]=prvdis0[];
for (int i=;i<m;i++)
prvdis[i]=prvdis0[i]+prvdis[i-];
for (int i=;i<m;i++)
seq[i]=seq0[i]-prvdis[i];
for (int i=;i<m;i++)
{
while (head<=tail && prvdis[i]-prvdis[que[head]]>clen/)head++;
if (head<=tail)
qres2[i]=seq[que[head]]+prvdis[i];
while (tail>=head && seq[que[tail]]<=seq[i])tail--;
que[++tail]=i;
}
head=,tail=-;
prvdis[]=prvdis0[];
for (int i=;i<m-;i++)
prvdis0[i]=prvdis0[i+];
prvdis0[m-]=prvdis0[m-m/-];
prvdis[m-]=prvdis0[m-];
for (int i=m-;i>=;i--)
prvdis[i]=prvdis0[i]+prvdis[i+];
for (int i=m-;i>=;i--)
seq[i]=seq0[i]-prvdis[i];
for (int i=m-;i>=;i--)
{
while (head<=tail && prvdis[i]-prvdis[que[head]]>clen/)head++;
if (head<=tail)
qres3[i]=seq[que[head]]+prvdis[i];
while (tail>=head && seq[que[tail]]<=seq[i])tail--;
que[++tail]=i;
}
return ;
}
qword solve2(int n)
{
prvdis[]=prvdis0[];
for (int i=;i<n;i++)
prvdis[i]=prvdis[i-]+prvdis0[i];
for (int i=;i<n;i++)
val1[i]=seq0[i]-prvdis[i];
for (int i=;i<n;i++)
val2[i]=seq0[i]+prvdis[i];
Build_sgt(,,n-);
int x;
qword res=INF;
for (int i=;i<n;i++)
{
x=i;
pair<qword,int> r1,r2,r3;
pair<qword,int> ra,rb;
if (i>x)
{
r1=Query_sgt1(,,x-);
r1.first+=prvdis[x]+seq0[x];
r2=Query_sgt2(,x+,i-);
r2.first+=-prvdis[x]+seq0[x];
r3=Query_sgt1(,i,n-);
r3.first+=prvdis[n-];
r3.first+=prvdis[x]+seq0[x];
ra=max(r1,r2);
ra=max(ra,r3);
}else
{
r1=Query_sgt1(,i,x-);
r1.first+=prvdis[x]+seq0[x];
r2=Query_sgt2(,x+,n-);
r2.first+=-prvdis[x]+seq0[x];
r3=Query_sgt2(,,i-);
//r3.first+=-prvdis[0];
r3.first+=(prvdis[n-]-prvdis[x])+seq0[x];
ra=max(r1,r2);
ra=max(ra,r3);
}
x=ra.second;
if (i>x)
{
r1=Query_sgt1(,,x-);
r1.first+=prvdis[x]+seq0[x];
r2=Query_sgt2(,x+,i-);
r2.first+=-prvdis[x]+seq0[x];
r3=Query_sgt1(,i,n-);
r3.first+=prvdis[n-];
r3.first+=prvdis[x]+seq0[x];
rb=max(r1,r2);
rb=max(rb,r3);
}else
{
r1=Query_sgt1(,i,x-);
r1.first+=prvdis[x]+seq0[x];
r2=Query_sgt2(,x+,n-);
r2.first+=-prvdis[x]+seq0[x];
r3=Query_sgt2(,,i-);
//r3.first+=-prvdis[0];
r3.first+=(prvdis[n-]-prvdis[x])+seq0[x];
rb=max(r1,r2);
rb=max(rb,r3);
}
res=min(res,rb.first);
}
return res;
}
int main()
{
// freopen("input.txt","r",stdin);
int n;
int x,y,z;
scanf("%d",&n);
for (int i=;i<=n;i++)
{
scanf("%d%d%d",&x,&y,&z);
addedge(x,y,z);
addedge(y,x,z);
// V[x]->neg=V[y];V[y]->neg=V[x];
}
dfs();
Edge *ne;
int pn=chead;
for (int i=ctail;dfn[i]>=dfn[chead];pn=i,i=pnt[i])
{
for (ne=V[i];ne;ne=ne->next)
{
if (i==chead && (ne->np==ctail || ne->np==pn))continue;
if (i!=chead && (ne->np==pn || ne->np==pnt[i]))continue;
tdis[i]=max(tdis[i],dfs2(ne->np,i,ne->val1));
}
}
int l=;
for (int i=ctail;dfn[i]>=dfn[chead];i=pnt[i])
{
seq0[l]=seq[l]=tdis[i];
if (i==chead)
prvdis0[l+]=clen-(rdis[ctail]-rdis[chead]);
else
prvdis0[l+]=pdis[i];
l++;
}
prvdis0[]=prvdis0[l];
for (int i=;i<l;i++)
seq[l+i]=seq[i],seq0[l+i]=seq0[i],prvdis0[l+i]=prvdis0[i];
qword ans=INF;
for (int i=;i<=l;i++)
if (prvdis0[i]>clen/)
ans=min(ans,(prvdis0[i])+seq[i-]+seq[i]);
ans=solve2(l);
solve1(l*);
int la=l;
l=;
pn=chead;
for (int i=ctail;dfn[i]>=dfn[chead];pn=i,i=pnt[i])
{
int x1,x2;
if (i==chead)
{
x1=pn;x2=ctail;
}else
{
x1=pnt[i],x2=pn;
}
qword x=max(max(qres2[l],qres2[l+la]),max(qres3[l],qres3[l+la]));
addedge(++n,i,x);
addedge(i,n,x);
ans=max(ans,dfs3(i,x1,x2));
l++;
}
printf("%lld.%c\n",ans/,ans%?'':'');
}

bzoj 3242: [Noi2013]快餐店 章鱼图的更多相关文章

  1. bzoj 3242: [Noi2013]快餐店

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

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

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

  3. BZOJ - 3242 :快餐店 (基环树DP) 最小化半径

    题意:给定N点N边的无向连通图,现在让你在图中找一点作为餐厅,使得最远点距离这点最近. 思路:为了保留整数,我们求最小直径,最后去除2.  直径来源于两部分: 1,在外向树中: 那么就是树的直接,一棵 ...

  4. 【BZOJ 3242】 (环套树、线段树+树形DP?)

    3242: [Noi2013]快餐店 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 728  Solved: 390 Description 小T打算 ...

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

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

  6. 【BZOJ 3242】【UOJ #126】【CodeVS 3047】【NOI 2013】快餐店

    http://www.lydsy.com/JudgeOnline/problem.php?id=3242 http://uoj.ac/problem/126 http://codevs.cn/prob ...

  7. 「BZOJ 3242」「NOI 2013」快餐店「基环树」

    题意 基环树上找到一个点(可以在边上)使得它到树上最远点的距离最小,输出最小距离 题解 如果是一棵树,答案就是树的直径\(/2\) 如果是基环树,那么很好证明删去环上的某一条边是不影响答案的.于是断环 ...

  8. bzoj 1023: [SHOI2008]cactus仙人掌图 tarjan缩环&&环上单调队列

    1023: [SHOI2008]cactus仙人掌图 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1141  Solved: 435[Submit][ ...

  9. BZOJ3242/UOJ126 [Noi2013]快餐店

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

随机推荐

  1. iOS之CAKeyframeAnimation关键帧动画详解

    CABasicAnimation算是CAKeyFrameAnimation的 特殊情况,即不考虑中间变换过程,只考虑起始点与目标点就可以了.而CAKeyFrameAnimation则更复杂一些,允许我 ...

  2. C#基础篇01

    vs20vs2013快捷键小节: 1>: #region #endregion(用来折叠冗余代码) 2>:Ctril+K+D快速对其代码: 3>:Ctril+K+C注释选中代码 Ct ...

  3. 简单的实现QQ通信功能(五)

    第五部分:聊天界面的设计及代码 一:效果图及界面设计 1. 效果图: 2. 界面设计: (1)左上角显示朋友的头像和“某某正在和某某聊天”. (2)中间的聊天窗口用了一个ListView,视图用详细信 ...

  4. 搭建用友开发环境(基于碧桂园的nchome)

    1.解压uap_studio6.3 2.授权 3.解压ufjdk.rar到指定路径 4.配置java的环境变量 5.解压BGY50602.7z到指定目录 6.然后在studio中导入BYG5002 7 ...

  5. Android Animation 动画属性

    在 Android 中, Animation 动画效果的实现可以通过两种方式进行实现: 一种是 tweened animation 渐变动画,另一种是 frame by frame animation ...

  6. SQL Server自动化运维系列 - 监控磁盘剩余空间及SQL Server错误日志(Power Shell)

    需求描述 在我们的生产环境中,大部分情况下需要有自己的运维体制,包括自己健康状态的检测等.如果发生异常,需要提前预警的,通知形式一般为发邮件告知. 在所有的自检流程中最基础的一个就是磁盘剩余空间检测. ...

  7. spring线程池配置

    源自:http://zjriso.iteye.com/blog/771706 1.了解 TaskExecutor接口 Spring的TaskExecutor接口等同于java.util.concurr ...

  8. c#安全性、稳定性、高性能需要注重的点

    1.弱事件 2.类型安全(包括类型转换时可能的异常) 3.线程安全 5.装箱和拆箱 6.闭包传递局部变量时可能遇到的问题. 7.用于dictionary的键,要同时实现GetHashCode和Equa ...

  9. Sublime Text使用手记

    1.Package Control 输入python 命令安装,打开控制台输入下方代码运行即可.控制台打开可使用快捷键Ctrl+~ 或菜单栏中View> Show Console,可访问Pack ...

  10. DailyNote

    删除node-modules文件夹 npm install -g rimraf rimraf node_modules 绘制一条贝塞尔曲线: context.quadraticCurveTo(x1,y ...