Description
小T打算在城市C开设一家外送快餐店。送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方。 快餐店的顾客分布在城市C的N 个建筑中,这N 个建筑通过恰好N 条双向道路连接起来,不存在任何两条道路连接了相同的两个建筑。任意两个建筑之间至少存在一条由双向道路连接而成的路径。小T的快餐店可以开设在任一建筑中,也可以开设在任意一条道路的某个位置上(该位置与道路两端的建筑的距离不一定是整数)。 现给定城市C的地图(道路分布及其长度),请找出最佳的快餐店选址,输出其与最远的顾客之间的距离。
题解:
我是%栋老师的,感觉他写得很好啊。我又犯了个很sb的错误,首先我找环的时候就挺傻的,两次dfs,还没有把非树边给ban掉,于是就GG了……
代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=100010;
const int inf=2147483647;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
int n;
LL D,pre1[Maxn],pre2[Maxn],suf1[Maxn],suf2[Maxn],dd[Maxn],mx[Maxn];
int vis[Maxn],P1,P2,cir[Maxn],lenc=0;
LL sd[Maxn];
bool mark[Maxn];
struct Edge{int y,next;LL d;}e[Maxn<<1];
int last[Maxn],len=1;
void ins(int x,int y,LL d)
{
int t=++len;
e[t].y=y;e[t].d=d;
e[t].next=last[x];last[x]=t;
}
int ban;
void DFS1(int x,int fa)
{
vis[x]=1;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(y==fa)continue;
if(!vis[y])DFS1(y,x);
else P1=y,P2=x,D=e[i].d,ban=i;
}
}
bool DFS2(int x,int fa)
{
vis[x]=2;
bool flag=(x==P2);
if(flag)cir[++lenc]=x;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(y==fa||i==ban||(i^1)==ban)continue;
if(vis[y]!=2)
{
bool t=DFS2(y,x);
if(t)cir[++lenc]=x,dd[lenc-1]=e[i].d;
flag|=t;
}
}
mark[x]=flag;
return flag;
}
LL tt;
LL dfs(int x,int fa)
{
LL mx1=0,mx2=0;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(y==fa||mark[y])continue;
LL o=(LL)e[i].d+dfs(y,x);
if(o>mx1)mx2=mx1,mx1=o;
else if(o>mx2)mx2=o;
}
tt=max(tt,mx1+mx2);
return mx1;
}
int main()
{
LL tmp=0;
n=read();
for(int i=1;i<=n;i++)
{
int x=read(),y=read(),d=read();
ins(x,y,d),ins(y,x,d);
}
DFS1(1,0);
DFS2(P1,0);
dd[lenc]=D;
sd[0]=sd[1]=0;
for(int i=1;i<=lenc;i++)
{
tt=0;
mx[i]=dfs(cir[i],0);
tmp=max(tmp,tt);
if(i>1)sd[i]=sd[i-1]+(LL)dd[i-1];
}
pre1[1]=mx[1];
for(int i=2;i<=lenc;i++)pre1[i]=max(pre1[i-1],(LL)mx[i]+sd[i]);
suf1[lenc]=mx[lenc];
for(int i=lenc-1;i;i--)suf1[i]=max(suf1[i+1],(LL)mx[i]+sd[lenc]-sd[i]);
LL t;
t=mx[1];
pre2[1]=mx[1];
for(int i=2;i<=lenc;i++)
{
t+=(LL)dd[i-1];
pre2[i]=max(pre2[i-1],t+mx[i]);
t=max(t,mx[i]);
}
t=mx[lenc];
suf2[lenc]=mx[lenc];
for(int i=lenc-1;i;i--)
{
t+=(LL)sd[i+1]-sd[i];
suf2[i]=max(suf2[i+1],t+mx[i]);
t=max(t,mx[i]);
}
LL ans=max(tmp,pre2[lenc]);
for(int i=1;i<lenc;i++)
ans=min(ans,max(max(pre2[i],suf2[i+1]),max(pre1[i]+suf1[i+1]+D,tmp)));
printf("%.1lf",(double)ans/2.0);
}