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. Linux--------------安装vsftpd

    1.安装vsftpd        yum install -y vsftpd         yum -y install ftp vsftpd    2.安装vsftpd虚拟用户配置依赖包     ...

  2. 安装tensorflow

    官网:http://tensorflow.org/安装步骤:1.sudo apt-get install python-pip python-dev python-virtualenv 3    co ...

  3. RedHat6.1(64bit)安装JDK

    今天在服务器上装JDK1.5,费了不少力气,记录下来以供参考 服务器安装的操作系统为Red Hat 6.1(x86) [123@123 bin]$ cat /etc/redhat-release Re ...

  4. Java NIO Socket 非阻塞通信

    相对于非阻塞通信的复杂性,通常客户端并不需要使用非阻塞通信以提高性能,故这里只有服务端使用非阻塞通信方式实现 客户端: package com.test.client; import java.io. ...

  5. Javascript,闭包

    js变量的调用 一.全局变量函数调用 var n = 99; function f1() { alert(n); } f1();//99 在函数外部定义的变量,再函数中可以被调用,因为变量n,与f1在 ...

  6. js数组&&字符串&&定时器1

    一.简单计算命令eval var str="6*5"; alert(eval(str)); 注意:不安全,一般都不会去用   二.id&&name id:只能唯一 ...

  7. C# select的联动效果

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><html><head&g ...

  8. jquery 可拖动进度条

    实现这个效果怎么弄呢? <!DOCTYPE html> <html> <head lang="en"> <meta charset=&qu ...

  9. objective-c中是如何实现线程同步的?

    多线程在各种编程语言中都是难点,很多语言中实现起来很麻烦,objective-c虽然源于c,但其多线程编程却相当简单,可以与java相媲美.这篇文章主要从线程创建与启动.线程的同步与锁.线程的交互.线 ...

  10. 关于Spring AOP和IOC的一些总结

    Spring官方网站:https://spring.io/ 最早对象的创建是有new关键字,但是如果产生的类比较繁多或者复杂,就用工厂代替new关键字,但是工厂的控制能力有限,譬如对产生对象的生命周期 ...