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

时间:2023-03-09 00:28:36
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 2 1
1 4 2
1 3 2
2 4 1

Sample Output

2.0

HINT

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

数据范围

对于 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%?'':'');
}