PAT甲级1072
题目大意:给出用户数n(不超过1000),加油站数量m(不超过10),道路k条,加油站的最远供应范围ds。接下来给出k行,代表k条道路,其中G开头的代表加油站,让你选择一个合适的加油站,要求如下:
1、所有用户都必须在该加油站到该用户最短路径所能达到的范围内,即加油站到该用户的最短路径不能超过加油站的供应范围;
2、选择加油站到各个用户最短路径中路径最短的那条,该路径作为第一参照应尽可能的大;
3、如果碰到第一参照相同的情况下,则需要求出该加油站到各个用户的平均距离,该平均距离应尽可能的小,此为第二参照;
4、若第二参照也相同则按加油站编号从小到大的顺序选择序号最小的一个;
5、若不存在这样的加油站则输出No Solution
Dijkstra模拟最短路径的问题,可以多开辟几个数组记录平均距离以及最短距离,用户题目说了1~n,所以加油站可以设置为 n+1~n+m,若是碰到不满足题意的加油站则提前跳出。这里题目样例输出的是3.3,实际上平均距离是3.25,所以应该是四舍五入,但是博主四舍五入后第四个测试点不通过,直接按1位小数输出反而能过,可能是bug吧。(这里path是记录路径用的,但是这题没用到可以忽略)
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#define MAXN 1020
#define INF 100000000
using namespace std;
int n,m,k,ds;
bool visit[MAXN];
int road[MAXN][MAXN],dis[MAXN][MAXN];
double average[MAXN];
vector<int> path[MAXN];
void init(){
fill(visit+1,visit+n+m+1,false);
for(int i=1;i<=n+m;i++)
fill(road[i]+1,road[i]+n+m+1,INF);
for(int i=n+1;i<=n+m;i++)
fill(dis[i]+1,dis[i]+n+m+1,INF);
}
void Dijkstra(int index){
fill(visit+1,visit+n+m+1,false);
dis[index][index]=0;
for(int i=1;i<=m+n;i++){
int u=-1,min=INF;
for(int j=1;j<=m+n;j++)
if(!visit[j]&&dis[index][j]<min)
u=j,min=dis[index][j];
if(u==-1) return ;
visit[u]=true;
for(int j=1;j<=m+n;j++){
if(!visit[j]&&road[u][j]<INF&&dis[index][u]+road[u][j]<=dis[index][j]){
if(dis[index][u]+road[u][j]<dis[index][j]){
dis[index][j]=dis[index][u]+road[u][j];
path[j].clear();
path[j].push_back(u);
}else{
path[j].push_back(u);
}
}
}
}
}
void ave(int index){
double sum=0;
for(int i=1;i<=n;i++)
sum+=dis[index][i];
average[index]=sum/n;
}
int string_to_int(string a){
int toint;
if(a[0]!='G') toint=stoi(a);
else{
toint=n+stoi(a.substr(1,a.length()-1));
}
return toint;
}
int main(){
int h1,h2,length,minDis=-1,target=0;
string house1,house2;
scanf("%d%d%d%d",&n,&m,&k,&ds);
init();
for(int i=0;i<k;i++){ //前n个存放住户,后n+m个存放加油站
cin>>house1>>house2;
h1=string_to_int(house1);
h2=string_to_int(house2);
scanf("%d",&length);
road[h1][h2]=length;
road[h2][h1]=length;
}
for(int i=n+1;i<=n+m;i++){
Dijkstra(i);
ave(i);
int tmpDis=INF;
bool canBuilt=true;
for(int j=1;j<=n;j++){
if(dis[i][j]>ds){
canBuilt=false;
break;
}
if(dis[i][j]<tmpDis) tmpDis=dis[i][j];
}
if(canBuilt){
if(tmpDis>minDis) minDis=tmpDis,target=i;
else if(tmpDis==minDis){
if(average[i]<average[target]){
target=i;
}else if(average[i]==average[target]){
if(i<target) target=i;
}
}
}
// for(int j=1;j<=n;j++)
// printf("%d ",dis[i][j]);
// printf("\n");
}
if(minDis==-1) printf("No Solution");
else{
printf("G%d\n",target-n);
printf("%.1f %.1f",(double)minDis,average[target]);
}
system("pause");
return 0;
}