bzoj 3242: [Noi2013]快餐店 章鱼图
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 4 2
1 3 2
2 4 1
Sample Output
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]快餐店 章鱼图的更多相关文章
- bzoj 3242: [Noi2013]快餐店
Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...
- 3242: [Noi2013]快餐店 - BZOJ
Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...
- BZOJ - 3242 :快餐店 (基环树DP) 最小化半径
题意:给定N点N边的无向连通图,现在让你在图中找一点作为餐厅,使得最远点距离这点最近. 思路:为了保留整数,我们求最小直径,最后去除2. 直径来源于两部分: 1,在外向树中: 那么就是树的直接,一棵 ...
- 【BZOJ 3242】 (环套树、线段树+树形DP?)
3242: [Noi2013]快餐店 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 728 Solved: 390 Description 小T打算 ...
- P1399 [NOI2013] 快餐店 方法记录
原题题面P1399 [NOI2013] 快餐店 题目描述 小 T 打算在城市 C 开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小 T 希望快餐店的地址选在离最 ...
- 【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 ...
- 「BZOJ 3242」「NOI 2013」快餐店「基环树」
题意 基环树上找到一个点(可以在边上)使得它到树上最远点的距离最小,输出最小距离 题解 如果是一棵树,答案就是树的直径\(/2\) 如果是基环树,那么很好证明删去环上的某一条边是不影响答案的.于是断环 ...
- bzoj 1023: [SHOI2008]cactus仙人掌图 tarjan缩环&&环上单调队列
1023: [SHOI2008]cactus仙人掌图 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 1141 Solved: 435[Submit][ ...
- BZOJ3242/UOJ126 [Noi2013]快餐店
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
随机推荐
- 100 high quality blogs from java developers
This list collects 100 high quality blogs from Java developers from all over the world. Some of thes ...
- oracle根据pid查询出正在执行的执行语句
今天数据库访问突然很慢,通过top命令发现oracle的cpu使用率很高.同事建议查询一下看看是什么语句导致的oracle运行变慢.于是从网上查了一下,可以根据pid查询出正在执行的查询语句,发现是一 ...
- Atom编辑器入门到精通(一) 安装及使用基础
为什么选择使用Atom Atom是GitHub推出的一款编辑器,被称为21世纪的黑客编辑器,主要的特点是现代,易用,可定制.我之前用过多款编辑器,现在来总结一下个人对各编辑器的看法: Vim是我用的时 ...
- 数据交互 ajax代码整理
请求列表通用 /** **加载对应的试卷套题 ** */ function loadQuestions(){ var businessSubClass = { pageNo:pageNo, pageS ...
- 使用ASP.NET实现Windows Service定时执行任务
转载http://blog.csdn.net/yanghua_kobe/article/details/6937816 我们怎样才能在服务器上使用asp.net定时执行任务而不需要安装windows ...
- C# 自定义排序
/// <summary> /// 实体 /// </summary> public class Product { public int ID { get; set; } p ...
- Java并发编程:进程和线程之由来__进程让操作系统的并发性成为可能,而线程让进程的内部并发成为可能
转载自海子:http://www.cnblogs.com/dolphin0520/p/3910667.html Java多线程基础:进程和线程之由来 在前面,已经介绍了Java的基础知识,现在我们来讨 ...
- (转)IOS 学习笔记 2015-03-23 如何获取IOS程序的系统信息
首页 > 程序开发 > 移动开发 > IOS > 正文 iOS 获取手机的型号,系统版本,软件名称,软件版本 -- 个评论 作者:vipa1888 收藏 我要投稿 网上搜索出来 ...
- 浅析JAVA设计模式(三)
4.接口隔离原则: ISP(Interface Segregation Principle) 客户端不应该依赖它不需要的接口,或者说类的依赖的关系应该建立在最小的接口上.举个例子,直接上代码: 1 ...
- spark - 将RDD保存到RMDB(MYSQL)数据库中
SCALA连接数据库批量插入: scala> import java.sql.DriverManager scala> var url = "jdbc:mysql://local ...