【1072 30 Dijkstra】 Gas Station

传送门

题意

给定\(n\)个居民地,\(m\)个候选加油站,\(k\)条边,\(d_{s}\)为居民地到加油站的最大距离,选出一个加油站满足到所有居民地的距离小于\(d_{s}\),其到居民地的最短距离是所有中最大的,如果相同选取到所有居民地平均距离最小的,再相同选取\(id\)小的

数据范围

\(n\leq 1000\)
\(m\leq 10\)
\(k\leq 10^{4}\)

题解

  • 加油站到居民地可以途径候选加油站
  • 暴力以每个加油站为起点求到所有点的最短路
  • 统计\(min,average\),更新答案

Code

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
const int INF=0x3f3f3f3f,N=1030;
map<string,int>mp;
map<int,string>ump;
int n,m,k,ds,d[N],g[N][N];
bool st[N];

void dijkjstra(int gas){
    memset(d,0x3f,sizeof d);
    memset(st,0,sizeof st);
    d[gas]=0;
    for(int i=0;i<n+m;i++){
        int t=-1;
        for(int j=1;j<=n+m;j++)
            if(!st[j] && (t==-1 || d[t]>d[j])) t=j;
        if(t==-1) return;
        st[t]=1;
        for(int j=1;j<=n+m;j++)
            if(!st[j] && g[t][j]!=INF && d[j]>d[t]+g[t][j]) 
                d[j]=d[t]+g[t][j];
    }
}
int main(){
    memset(g,0x3f,sizeof g);
    scanf("%d%d%d%d",&n,&m,&k,&ds);
    string x="G";
    for(int i=1;i<=n;i++) {string t=to_string(i);mp[t]=i;}
    for(int i=1;i<=m;i++) 
        {x+=to_string(i); mp[x]=n+i; ump[n+i]=x; x="G"; }

    for(int i=0;i<k;i++){
        int dis; string a,b; cin>>a>>b; scanf("%d",&dis);
        int u=mp[a],v=mp[b];
        g[u][v]=g[v][u]=dis;
    }
    int id=-1;
    double minmax=-1,min_avg=INF;
    for(int i=n+1;i<=m+n;i++) {
        double avg=0,mi = INF;
        dijkjstra(i);
        for(int i=1;i<=n;i++) {
            if(d[i] > ds) {mi=-1;break;}
            if(d[i]<mi) mi=d[i];
            avg += 1.0*d[i];
        }
        if(mi==-1) continue;
        
        avg = avg/n;
        if(mi > minmax) {
            minmax=mi;
            min_avg=avg; 
            id=i;
        }
        else if(mi == minmax && avg < min_avg){
            min_avg=avg; 
            id=i;
        }
    }

    if(id!=-1) 
        printf("%s\n%.1lf %.1lf",ump[id].c_str(),minmax, min_avg);
    else printf("No Solution");
}
posted @ 2021-03-03 14:23  Hyx'  阅读(51)  评论(0)    收藏  举报