题目描述
大家倒垃圾的时候,都希望垃圾箱距离自己比较近,但是谁都不愿意守着垃圾箱住。所以垃圾箱的位置必须选在到所有居民点的最短距离最长的地方,同时还要保证每个居民点都在距离它一个不太远的范围内。
现给定一个居民区的地图,以及若干垃圾箱的候选地点,请你推荐最合适的地点。如果解不唯一,则输出到所有居民点的平均距离最短的那个解。如果这样的解还是不唯一,则输出编号最小的地点。
输入格式
输入第一行给出4个正整数:N(≤10^3 )是居民点的个数;M(≤10)是垃圾箱候选地点的个数;K(≤10^4 )是居民点和垃圾箱候选地点之间的道路的条数;DS 是居民点与垃圾箱之间不能超过的最大距离。所有的居民点从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
测试点4过不了,难受……
C++ 代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3+20;
int g[N][N];
int n,m,k,Ds,dis[N];
bool st[N];
int ans=-1;
double minD=-1,minavg;
void bfs(int start)
{
memset(st,0,sizeof st);
memset(dis,0x3f,sizeof dis);
dis[start]=0;
queue<int> q;
q.push(start);
st[start]=true;
while(q.size())
{
auto t = q.front();
q.pop();
for(int i=1;i<=n+m;i++)
{
dis[i]=min(dis[i],dis[t]+g[t][i]);
if(!st[i] && g[t][i]<0x3f3f3f3f/2)
{
q.push(i);
st[i]=true;
}
}
}
double mind=0x3f3f3f3f,avg=0;
for(int i=1;i<=n;i++)
{
if(dis[i]>Ds) return ;
avg+=(double)dis[i];
if(mind>dis[i]) mind=dis[i];
}
avg=(double)((avg+0.05)/double(n)); //保留一位小数,+0.05
mind=(double)(mind+0.05);
if(mind > minD)
{
ans = start-n;
minD = mind;
minavg = avg;
}
else if(mind == minD && avg < minavg)
{
ans = start-n;
minavg = avg;
}
}
int main()
{
memset(g,0x3f,sizeof(g));
cin>>n>>m>>k>>Ds;
string a,b;
int d;
for(int i=0;i<k;i++)
{
int a1,b1;
cin>>a>>b>>d;
if(a[0]=='G')
{
a=a.substr(1);
a1=stoi(a)+n;
}
else a1=stoi(a);
if(b[0]=='G')
{
b=b.substr(1);
b1=stoi(b)+n;
}
else b1=stoi(b);
//cout<<a1<<" "<<b1<<endl;
g[a1][b1]=g[b1][a1]=d;
}
for(int i=n+1;i<=n+m;i++)
{
bfs(i);
}
if(ans==-1) puts("No Solution");
else{
cout<<"G"<<ans<<endl;
printf("%.1f %.1f",minD,minavg);
}
return 0;
}