PAT甲题题解-1072. Gas Station (30)-dijkstra最短路

题意:从m个加油站里面选取1个站点,使得其离住宅的最近距离mindis尽可能地远,并且离所有住宅的距离都在服务范围ds之内。
如果有很多相同mindis的加油站,输出距所有住宅平均距离最小的那个。
如果平均值还是一样,就输出按照顺序排列加油站编号最小的。

分析:
加油站之间也是彼此有路连接的,所以最短路径计算的时候也要把加油站算上,是双向边,所以边的数组大小得开两倍。
加油站编号记为n+1~n+m,对这些点用dijkstra计算最短路径即可,这里顺便在dijkstra中进行了剪枝处理,不剪枝也没事。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <queue>
#define INF 0X3f3f3f3f
using namespace std;
/*
从m个加油站里面选取1个站点,使得其离住宅的最近距离mindis尽可能地远,并且离所有住宅的距离都在服务范围ds之内。
如果有很多相同mindis的加油站,输出距所有住宅平均距离最小的那个。
如果平均值还是一样,就输出按照顺序排列加油站编号最小的。
分析:
加油站之间也是彼此有路连接的,所以最短路径计算的时候也要把加油站算上,是双向边,所以边的数组大小得开两倍。
加油站编号记为n+1~n+m,对这些点用dijkstra计算最短路径即可,这里顺便在dijkstra中进行了剪枝处理,不剪枝也没事。
*/
const int maxn=1000+15;
int dis[maxn];
int vis[maxn];
int head[maxn];
int tot=0;
int mindis;
struct Node{
    int u;
    int dis;
    bool operator<(const Node tmp)const{
        return dis>tmp.dis;
    }
};

struct Edge{
    int to;
    int next;
    int dist;
}edge[10005*2];

void add(int u,int v,int dist){
    edge[tot].to=v;
    edge[tot].dist=dist;
    edge[tot].next=head[u];
    head[u]=tot++;
}
void init(){
    memset(head,-1,sizeof(head));
    tot=0;
}
bool dijkstra(int s,int n){
    for(int i=0;i<maxn;i++){
        dis[i]=INF;
        vis[i]=0;
    }
    priority_queue<Node>q;
    Node st,t;
    st.u=s;
    st.dis=0;
    dis[s]=0;
    q.push(st);
    bool first=true;
    while(!q.empty()){
        st=q.top();
        q.pop();
        vis[st.u]=1;
        if(first && 1<=st.u && st.u<=n){
            if(dis[st.u]<mindis){
                return false; //剪枝,即离车站最小的距离比目前的mindis还要小,直接返回即可
            }
            first=false;
        }
        for(int k=head[st.u];k!=-1;k=edge[k].next){
            int v=edge[k].to;
            if(!vis[v] && dis[st.u]+edge[k].dist<dis[v]){
                dis[v]=dis[st.u]+edge[k].dist;
                t.u=v;
                t.dis=dis[v];
                q.push(t);
            }
        }
    }
    return true;
}
int main()
{
    int n,m,k,ds;
    char str1[10],str2[10];
    int u,v,dist;
    scanf("%d %d %d %d",&n,&m,&k,&ds);
    init();
    for(int i=0;i<k;i++){
        scanf("%s %s %d",str1,str2,&dist);
        if(str1[0]=='G')
            u=atoi(str1+1)+n;
        else
            u=atoi(str1);
        if(str2[0]=='G')
            v=atoi(str2+1)+n;
        else
            v=atoi(str2);
        add(u,v,dist);
        add(v,u,dist);
    }
    mindis=0;
    double avgdis=INF;
    int gasid=0;
    bool noAns=true;
    for(int i=1;i<=m;i++){
        //如果最小距离小于目前的mindis,直接跳过
        if(!dijkstra(n+i,n)){
            continue;
        }
        dist=INF;
        int sum=0;
        bool flag=true;
        for(int j=1;j<=n;j++){
            //有超出服务范围的
            if(dis[j]>ds){
                flag=false;
                break;
            }
            dist=min(dist,dis[j]);
            sum+=dis[j];
        }
        if(!flag)
            continue;
        else
            noAns=false;
        double avg=sum*1.0/n;
        if(dist>mindis){
            gasid=i;
            mindis=dist;
            avgdis=avg;
        }
        else if(dist==mindis){
            if(avg<avgdis){
                gasid=i;
                avgdis=avg;
            }
        }
    }
    if(noAns)
        printf("No Solution
");
    else
        printf("G%d
%.1lf %.1lf
",gasid,(double)mindis,avgdis);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/chenxiwenruo/p/6390676.html