大家倒垃圾的时候,都希望垃圾箱距离自己比较近,但是谁都不愿意守着垃圾箱住。所以垃圾箱的位置必须选在到所有居民点的最短距离最长的地方,同时还要保证每个居民点都在距离它一个不太远的范围内。
现给定一个居民区的地图,以及若干垃圾箱的候选地点,请你推荐最合适的地点。如果解不唯一,则输出到所有居民点的平均距离最短的那个解。如果这样的解还是不唯一,则输出编号最小的地点。
输入格式:
输入第一行给出4个正整数:N(≤103)是居民点的个数;M(≤10)是垃圾箱候选地点的个数;K(≤104)是居民点和垃圾箱候选地点之间的道路的条数;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
即使不放垃圾箱,那一点也能走。不用四舍五入
//卧槽,最后一个测试样例一直过不去,结果把+0.05去掉就过了,它第一个样例有毒吧
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int g[1100][1100],dis[10010],b[10010],n,m,k,ds,ans=0,u,v,t,l=0;
double tt,av;
string s;
int ge(int l,int r)
{
int tt=0;
for(int i=l;i<=r;i++)
tt=tt*10+s[i]-'0';
return tt;
}
void sear(int x)
{
int tip=n+m;
for(int i=1;i<=tip;i++)
{
b[i]=0;
if(g[x][i]) dis[i]=g[x][i];
else dis[i]=0x3f3f3f3f;
}
b[x]=1;dis[x]=0;
while(1)
{
tt=0x3f3f3f3f;
for(int i=1;i<=tip;i++)
if(b[i]==0&&dis[i]<tt)
{
tt=dis[i];t=i;
}
if(tt==0x3f3f3f3f) break;
b[t]=1;
for(int i=1;i<=tip;i++)
if(b[i]==0&&g[t][i])
dis[i]=min(dis[i],dis[t]+g[t][i]);
}
tt=0;t=0x3f3f3f3f;
for(int i=1;i<=n;i++)
{
if(dis[i]>ds) return;
if(dis[i]<t) t=dis[i];
tt+=dis[i];
}
if(t>l||(t==l&&tt<av)) ans=x,l=t,av=tt;
}
int main()
{
ios::sync_with_stdio(false);
memset(g,0x3f3f3f3f,sizeof(g));
cin>>n>>m>>k>>ds;
while(k--)
{
cin>>s;
u=0;v=0;
if(s[0]!='G') u=ge(0,s.length()-1);
else u=ge(1,s.length()-1)+n;
cin>>s;
if(s[0]!='G') v=ge(0,s.length()-1);
else v=ge(1,s.length()-1)+n;
cin>>t;
g[u][v]=min(g[u][v],t);
g[v][u]=min(g[v][u],t);
}
for(int i=1;i<=m;i++)
sear(i+n);
if(ans) cout<<'G'<<ans-n<<endl<<fixed<<setprecision(1)<<(l*1.0)<<" "<<fixed<<setprecision(1)<<av/n;
else cout<<"No Solution";
return 0;
}