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
",0.5*ans);
    return 0;
}
center
原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/13908335.html