很明显就是一道最短路的题,且为多源最短路,用m次dijkstra算法求每个垃圾箱到各个居民点的最短距离,根据题意更新最优解。
#include <iostream>
#include <cstring>
#include <vector>
#define N 1020
#define inf 0x3f3f3f3f
using namespace std;
int n,m,k,ds,ansid,ansd,ansum;
vector<int> ver[N],we[N];
int read(){//读入边,垃圾箱编号为i+n
char s[10];
scanf("%s",s);
int i=0,res=0,flag=0;
if(s[0]=='G') i++,flag=1;
for(;s[i]!='\0';i++) res=res*10+s[i]-'0';
if(flag) res+=n;
return res;
}
void dijk(int s){//单源最短路
int dist[N],vis[N]={0};
memset(dist,0x3f,sizeof dist);
for(int i=0;i<ver[s].size();i++)
dist[ver[s][i]]=we[s][i];
dist[s]=0;
vis[s]=1;
while(1){
int p=-1,minn=inf;
for(int i=1;i<=n+m;i++){
if(!vis[i]&&dist[i]<minn)
minn=dist[i],p=i;
}
if(p==-1) break;
vis[p]=1;
for(int i=0;i<ver[p].size();i++){
if(!vis[ver[p][i]]&&dist[ver[p][i]]>dist[p]+we[p][i])
dist[ver[p][i]]=dist[p]+we[p][i];
}
}
int maxd=0,mind=inf,sum=0;
for(int i=1;i<=n;i++){//判断是否合理,求最大值、最小值、距离和
if(!vis[i]) return;
maxd=max(maxd,dist[i]);
mind=min(mind,dist[i]);
sum+=dist[i];
}
if(maxd>ds) return;//不合法
if(mind>ansd) ansid=s-n,ansd=mind,ansum=sum;//更新答案
else if(mind==ansd&&sum<ansum) ansid=s-n,ansum=sum;
}
int main(){
scanf("%d%d%d%d",&n,&m,&k,&ds);
while(k--){
int u,v,w;
u=read(); v=read(); scanf("%d",&w);
ver[u].push_back(v);we[u].push_back(w);
ver[v].push_back(u);we[v].push_back(w);
}
for(int i=n+1;i<=n+m;i++) dijk(i);//m次dijkstra
if(ansid==0) printf("No Solution\n");
else printf("G%d\n%.1lf %.1lf\n",ansid,(double)ansd,(100.0*ansum+0.5)/n/100);
return 0;
}