L3-005. 垃圾箱分布 (多次最短路)

L3-005. 垃圾箱分布

时间限制
200 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
陈越

大家倒垃圾的时候,都希望垃圾箱距离自己比较近,但是谁都不愿意守着垃圾箱住。所以垃圾箱的位置必须选在到所有居民点的最短距离最长的地方,同时还要保证每个居民点都在距离它一个不太远的范围内。

现给定一个居民区的地图,以及若干垃圾箱的候选地点,请你推荐最合适的地点。如果解不唯一,则输出到所有居民点的平均距离最短的那个解。如果这样的解还是不唯一,则输出编号最小的地点。

输入格式:

输入第一行给出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

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
#define LL long long
#define lt x<<1
#define rt x<<1|1
const int maxn = 1e5+111;
const int inf = 0x3f3f3f3f;
int mp[1020][1020];
int dis[1020];
int n,m,k,ds;
int f(char s[])
{
	int len = (int)strlen(s);
	if(s[0]=='G'){
		int sum=0;
		for(int i=1;i<len;i++)
			sum=sum*10+s[i]-'0';
		return sum+n;
	}else{
		int sum=0;
		for(int i=0;i<len;i++)
			sum=sum*10+s[i]-'0';
		return sum;
	}
}
int ans_flag=0;
int ans_Max=0;
int ans_sum;

void dij(int s)
{
	int vis[maxn];
	int nn=n+m;
	for(int i=1;i<=nn;i++) dis[i]=inf,vis[i]=0;
	dis[s]=0;
	for(int i=1;i<=nn;i++){
		int k=0;
		int Min=inf;
		for(int j=1;j<=nn;j++){
			if(!vis[j]&&Min>dis[j]){
				k=j;
				Min=dis[j];
			}
		}
		if(!k) break;
		vis[k]=1;
		for(int j=1;j<=nn;j++){
			if(dis[j]>dis[k]+mp[k][j]){
				dis[j]=dis[k]+mp[k][j];
			}
		}
	}
	int Min=inf;
	int sum=0;
	for(int i=1;i<=n;i++){
		if(dis[i]>ds)
			return;
		Min=min(Min,dis[i]);
		sum+=dis[i];
	}
	if(ans_Max<Min){
		ans_Max=Min;
		ans_flag=s-n;
		ans_sum=sum;
	}else if(ans_Max==Min){
		if(ans_sum>sum){
			ans_sum=sum;
			ans_flag=s-n;
		}else if(ans_sum==sum){
			ans_flag=min(ans_flag,s-n);
		}
	}

}

int main()
{
	memset(mp,inf,sizeof mp);
	scanf("%d %d %d %d",&n,&m,&k,&ds);
	for(int i=1;i<=k;i++){
		char s1[5],s2[5];
		scanf("%s %s",s1,s2);
		int u=f(s1);
		int v=f(s2);
		int w;scanf("%d",&w);
		if(w<mp[u][v])
			mp[u][v]=mp[v][u]=w;
	}

	for(int i=1;i<=m;i++){
		dij(n+i);
	}
	if(ans_flag==0){
		printf("No Solution\n");
	}else{
		printf("G%d\n",ans_flag);
		printf("%0.1lf %0.1lf\n",1.0*ans_Max,1.0*ans_sum/n+1e-8);
	}



	
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值