L3-005 垃圾箱分佈 (30分)
大家倒垃圾的時候,都希望垃圾箱距離自己比較近,但是誰都不願意守着垃圾箱住。所以垃圾箱的位置必須選在到所有居民點的最短距離最長的地方,同時還要保證每個居民點都在距離它一個不太遠的範圍內。
現給定一個居民區的地圖,以及若干垃圾箱的候選地點,請你推薦最合適的地點。如果解不唯一,則輸出到所有居民點的平均距離最短的那個解。如果這樣的解還是不唯一,則輸出編號最小的地點。
輸入格式:
輸入第一行給出4個正整數:N(≤103 )是居民點的個數;M(≤10)是垃圾箱候選地點的個數;K(≤104)是居民點和垃圾箱候選地點之間的道路的條數;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
開始看題看到“最小最大”,以爲要用二分,有點不敢想象pta也出二分了,看完題並不是,是最短路,看着有點麻煩,不過最近練最短路了。還沒寫就喫午飯了,邊喫邊想這個好麻煩啊。。。
反正這題不算難,就是麻煩,開始還定義二維數組了,也沒必要。這題的關鍵點就是垃圾候選點也可以通過,開始不敢確定,手寫模擬一遍才確定的,剩下的也沒啥,輸入的時候麻煩一點,跑n次最短路就好了,最後再比較一下。段錯誤一次開大內存就對了。
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<queue>
#include<iostream>
using namespace std;
int inf=0x3f3f3f3f;
const int N=110000;
int dis[N],head[N];
int n,m,num=0;
struct node{
int to,value,next;
}s[N*2];
void add(int u,int v,int value){
s[++num].next=head[u];
s[num].to=v;
s[num].value=value;
head[u]=num;
}
void spfa(int x){
queue<int>q;
memset(dis,inf,sizeof(dis));
int i;
dis[n+x]=0;
q.push(n+x);
while(!q.empty()){
int t=q.front();
q.pop();
for(i=head[t];i;i=s[i].next){
int to=s[i].to;
if(dis[to]>dis[t]+s[i].value){
dis[to]=dis[t]+s[i].value;
q.push(to);
}
}
}
}
int main()
{
int x,y,i,j,k,d,v;
char s1[10],s2[10];
scanf("%d %d %d %d",&n,&m,&k,&d);
while(k--){
scanf("%s %s %d",&s1,&s2,&v);
if(s1[0]!='G'&&s2[0]!='G'){
x=y=0;
for(i=0;s1[i];i++)
x=x*10+s1[i]-'0';
for(i=0;s2[i];i++)
y=y*10+s2[i]-'0';
add(x,y,v);
add(y,x,v);
}
else if(s1[0]!='G'&&s2[0]=='G'){
x=0;
y=n;
for(i=0;s1[i];i++)
x=x*10+s1[i]-'0';
if(strlen(s2)==3)
y+=10;
else y+=s2[1]-'0';
add(x,y,v);
add(y,x,v);
}
else if(s1[0]=='G'&&s2[0]!='G'){
x=n;
y=0;
if(strlen(s1)==3)
x+=10;
else x+=s1[1]-'0';
for(i=0;s2[i];i++)
y=y*10+s2[i]-'0';
add(x,y,v);
add(y,x,v);
}
else if(s1[0]=='G'&&s2[0]=='G'){
x=y=n;
if(strlen(s1)==3)
x+=10;
else x+=s1[1]-'0';
if(strlen(s2)==3)
y+=10;
else y+=s2[1]-'0';
add(x,y,v);
add(y,x,v);
}
}
int ansg,ansm=-inf,ansa=inf;
for(i=1;i<=m;i++){
spfa(i);
int flag=0,a1=inf,a2=0;
for(j=1;j<=n;j++){
if(dis[j]>d) {
flag=1;break;
}
if(dis[j]<a1)
a1=dis[j];
a2+=dis[j];
}
if(!flag){
if((ansm<a1)||(ansm==a1&&a2<ansa)){
ansg=i;
ansm=a1;
ansa=a2;
}
}
}
if(ansa==inf) printf("No Solution");
else printf("G%d\n%.1f %.1f",ansg,(double)ansm,(double)ansa/n);
return 0;
}