7-14 垃圾箱分布 (30 分)
大家倒垃圾的时候,都希望垃圾箱距离自己比较近,但是谁都不愿意守着垃圾箱住。所以垃圾箱的位置必须选在到所有居民点的最短距离最长的地方,同时还要保证每个居民点都在距离它一个不太远的范围内。
现给定一个居民区的地图,以及若干垃圾箱的候选地点,请你推荐最合适的地点。如果解不唯一,则输出到所有居民点的平均距离最短的那个解。如果这样的解还是不唯一,则输出编号最小的地点。
输入格式:
输入第一行给出4个正整数:N(≤10
3
)是居民点的个数;M(≤10)是垃圾箱候选地点的个数;K(≤10
4
)是居民点和垃圾箱候选地点之间的道路的条数;D
S
是居民点与垃圾箱之间不能超过的最大距离。所有的居民点从1到N编号,所有的垃圾箱候选地点从G1到GM编号。
随后K行,每行按下列格式描述一条道路:
P1 P2 Dist
其中P1和P2是道路两端点的编号,端点可以是居民点,也可以是垃圾箱候选点。Dist是道路的长度,是一个正整数。
输出格式:
首先在第一行输出最佳候选地点的编号。然后在第二行输出该地点到所有居民点的最小距离和平均距离。数字间以空格分隔,保留小数点后1位。如果解不存在,则输出No Solution。
输入样例1:
4 3 11 5
1 2 2
1 4 2
1 G1 4
1 G2 3
2 3 2
2 G2 1
3 4 2
3 G3 2
4 G1 3
G2 G1 1
G3 G2 2
输出样例1:
G1
2.0 3.3
输入样例2:
2 1 2 10
1 G1 9
2 G1 20
输出样例2:
No Solution
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e4;
ll dis[N];
int vist[N];
int n,m,k,d;
struct Node{
ll dian;
ll zhi;
friend bool operator<(const Node& a,const Node& b)
{
return a.zhi>b.zhi;
}
};
vector<Node> v[N];
int getNum(string s)
{
if(s[0]=='G'){
return s[1]-'0'+n;
}
else{
int ans=0;
for(int i=0;i<s.size();i++){
int t=s[i]-'0';
ans=ans*10+t;
}
return ans;
}
}
void dj(int x)
{
priority_queue<Node> q;
memset(dis,0x3f3f3f,sizeof(dis));
memset(vist,0,sizeof(vist));
q.push({x,0}); //入对
dis[x]=0;
while(!q.empty()){
Node H=q.top();
q.pop();
int cur=H.dian;
if(vist[cur]) continue; //如果走过,这跳过
vist[cur]=1;//标记走过
for(int i=0;i<v[cur].size();i++){
Node next=v[cur][i];
if(!vist[next.dian]&&dis[next.dian]>dis[cur]+next.zhi){
dis[next.dian]=dis[cur]+next.zhi;
q.push({next.dian,dis[next.dian]});//放入新的点和直接到点的距离
}
}
}
}
int main()
{
int i,j,zhi;
cin>>n>>m>>k>>d;
string s1,s2;
for(i=1;i<=k;i++){
cin>>s1>>s2;
int x=getNum(s1); //主要是处理垃圾同的,在居民点后+M
int y=getNum(s2);
cin>>zhi;
v[x].push_back({y,zhi});//双向边
v[y].push_back({x,zhi});
}
int id=0;
double ans=INT_MAX,dis1=0;
for(int i=n+1; i<=n+m; i++) //枚举全部垃圾桶
{
dj(i);
ll maxx=0;
ll minn=INT_MAX;
int sum=0;
for(int j=1; j<=n; j++)
{
minn=min(minn,dis[j]); //找出居民点到 垃圾桶的最短距离
sum+=dis[j];
maxx=max(maxx,dis[j]);//最长
}
if(maxx>d){ //不符合
continue;
}
double avg=sum*1.0/n;//预先计算平均数
if(minn>dis1){ //要最短路径总和中的最小距离的最大
dis1=minn;
id=i-n;
ans=avg; //注意这里要更新平均数
continue;
}
if(minn==dis1&&avg<ans){ //最小距离相等,要平均数最少的
dis1=minn;
id=i-n;
ans=avg;
}
}
if(ans==INT_MAX)
cout<<"No Solution"<<endl;
else
{
cout<<"G";
printf("%d\n%.1f %.1f",id,dis1,ans);
}
}