2020/10/23 模拟赛 center
Description
有一个城市的交通网络由$n$个结点和$m$条双向道路组成,每个结点有一个咖啡店。现在要选择某个位置(可以是结点,也可以是某条道路上的任意一点)建一个餐馆,使得餐馆到最远的咖啡厅的距离最近,输出这个距离,
Solution
先floyd求出任意两点之间最短路,然后枚举每条边,设$d_{1,i}$表示点$i$距离该边一个端点的距离,$d_{2,i}$同理,则题目所求为
$$\max_{i=1}^n \{ \min(d_{1,i}+x,d_{2,i}+w-x)$$
设集合$A$表示对于边上一时刻$x$,$d_{1,i}+x \leq d_{2,i}+w-x$的所有距离,$B$为其补集,那么所求为
$$\max ( \max{A}+x,\max {B+w-x})$$
从小到大扫描每一个时刻点,维护两个集合的最大值即可
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> using namespace std; int n,m,tot,head[205],dist[205][205],sav[205][205],w,g[205],d1[205],d2[205],ans=1<<30; struct Edge { int sta,to,w; }edge[80005]; struct Node { int x,val; bool operator < (const Node &z)const { return val<z.val; } }node[205]; inline int read() { int f=1,w=0; char ch=0; while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { w=(w<<1)+(w<<3)+ch-'0'; ch=getchar(); } return f*w; } bool cmp(int x,int y) { return d1[x]>d1[y]; } int main() { memset(dist,127,sizeof(dist)); n=read(); m=read(); for(int i=1;i<=m;i++) { int x=read(),y=read(),c=read(); dist[x][y]=dist[y][x]=c; edge[++tot]=(Edge){x,y,c}; edge[++tot]=(Edge){y,x,c}; } for(int k=1;k<=n;k++) { for(int i=1;i<=n;i++) { dist[i][i]=0; for(int j=1;j<=n;j++) { dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]); } } } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { d1[j]=dist[i][j]; sav[i][j]=j; } sort(sav[i]+1,sav[i]+n+1,cmp); } for(int T=1;T<=tot;T++) { int x1=edge[T].sta,x2=edge[T].to; for(int i=1;i<=n;i++) { d1[i]=dist[x1][i]; d2[i]=dist[x2][i]; } w=edge[T].w; for(int i=1;i<=n;i++) { int temp=d2[i]-d1[i]+w; if(temp<0) { temp=0; } if(temp>2*w) { temp=2*w; } node[i]=(Node){i,temp}; g[i]=temp; } int pos=1,maxx1=0,maxx2=0; sort(node+1,node+n+1); for(int i=1;i<=n;i++) { int j=i; while(g[sav[x1][pos]]<=node[i].val&&pos<=n) { ++pos; } while(node[i].val==node[j].val&&j<=n) { maxx2=max(maxx2,d2[node[j].x]); ++j; } if(pos<=n) { maxx1=d1[sav[x1][pos]]; } else { maxx1=maxx2; } int lx=node[i].val,rx=node[j].val,x=maxx2-maxx1+w; if(lx<=x&&x<=rx) { ans=min(ans,maxx1*2+x); } else { int w1=maxx1*2+lx,w2=(maxx2+w)*2-lx; ans=min(ans,max(w1,w2)); w1=maxx1*2+rx; w2=(maxx2+w)*2-rx; ans=min(ans,max(w1,w2)); } i=j-1; } } printf("%.2lf\n",0.5*ans); return 0; }