poj 2607 Fire Station

题目描述:某个城市的消防任务由一些消防站承担。有些居民抱怨离他们家最近的消防站距离太远了,所以市政府决定在修建一个新的消防站。试选择消防站的位置,以减小这些居民离家最近的消防站的距离。


思路:其实这题是一个最短路径的枚举,用dist[i]表示i号路口距离最近的消防站的距离,先求出已经存在的消防站的最短路径,更新dist数组,然后枚举剩下的路口,更新dist求出最小值。此题可以用floyd先求出所有的最短路径,然后再去更新比较,不过效率不高用时1797ms。用优化的spfa只需79ms.


floyd代码:

#include <iostream>
#include <algorithm>
#include <cstdio>

using namespace std;

const int inf = 1000000000;
const int maxn = 505;

int f,n;
bool sta[maxn];//消防站 
int edge[maxn][maxn];
int dist[maxn];

bool input(){
	if(scanf("%d%d",&f,&n) != 2) return false;
	int x;
	for(int i = 1; i <= n; i++) sta[i] = false;
	for(int i = 0; i < f; i++){
		scanf("%d",&x);
		sta[x] = true;
	}	
	
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= n; j++){
			if(i == j) edge[i][j] = 0;
			else edge[i][j] = inf;
		}
	}
	
	int u,v,w;
	while(scanf("%d%d%d",&u,&v,&w) == 3){
		edge[u][v] = edge[v][u] = w;
	}
	return true;
}

void floyd(){	
	for(int k = 1; k <= n; k++){
		for(int i = 1; i <= n; i++){
			for(int j = 1; j <= n; j++){
				edge[i][j] = min(edge[i][j],edge[i][k]+edge[k][j]);
			}
		}
	}
}

void solve(){
	floyd();
	
	for(int i = 1; i <= n; i++) dist[i] = inf;
	
	//用已存在的消防站来确定每个路口离消防站的距离 
	for(int i = 1; i <= n; i++){
		if(!sta[i]) continue;
		for(int j = 1; j <= n; j++){
			dist[j] = min(dist[j],edge[i][j]);
		}
	}
	
	int index = 1;
	int minimum = inf;
	int t_dist[maxn];
	//放置消防站 
	for(int i = 1; i <= n; i++){
		if(sta[i]) continue;
		int maximum = -inf;
		for(int j = 1; j <= n; j++) t_dist[j] = dist[j];
		
		for(int j = 1; j <= n; j++){
			t_dist[j] = min(t_dist[j],edge[i][j]);
			maximum = max(t_dist[j],maximum);
		}
		if(maximum < minimum){
			minimum = maximum;
			index = i;
		}
		
	}
		
	printf("%d\n",index);
}

int main(){
	while(input()){
		solve();
	}
	return 0;
}

spfa代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>

using namespace std;

const int inf = 1000000000;
const int maxn = 505;


struct node{
	int v,w;
	
	node(int _v, int _w){
		v = _v, w = _w;
	}
};

int f,n;
bool sta[maxn];//消防站 
vector<node> list[maxn];
int dist[maxn];
bool inq[maxn];

bool input(){
	if(scanf("%d%d",&f,&n) != 2) return false;
	int x;
	for(int i = 1; i <= n; i++) sta[i] = false;
	for(int i = 0; i < f; i++){
		scanf("%d",&x);
		sta[x] = true;
	}	
	
	for(int i = 1; i <= n; i++) list[i].clear();
	
	int u,v,w;
	while(scanf("%d%d%d",&u,&v,&w) == 3){
		list[u].push_back(node(v,w));
		list[v].push_back(node(u,w));
	}
	return true;
}

void spfa(int s, int *d){
	queue<int> q;
	for(int i = 1; i <= n; i++){
		inq[i] = false;
	}
	d[s] = 0;
	q.push(s);
	while(!q.empty()){
		int u = q.front(); q.pop(); inq[u] = false;
		
		for(int i = 0; i < list[u].size(); i++){
			int v = list[u][i].v;
			int w = list[u][i].w;
			if(d[u] + w < d[v]){
				d[v] = d[u] + w;
				if(!inq[v]){
					q.push(v);
					inq[v] = true;
				}
			}
		}
		
	}
	
}

void solve(){
	
	for(int i = 1; i <= n; i++) dist[i] = inf;
	
	for(int i  = 1; i <= n; i++){
		if(sta[i]){
			spfa(i,dist);
		}
	}
	
	int index = 1;
	int minimum = inf;
	int t_dist[maxn];
	//放置消防站 
	for(int i = 1; i <= n; i++){
		if(sta[i]) continue;
		int maximum = -inf;
		for(int j = 1; j <= n; j++) t_dist[j] = dist[j];
		spfa(i,t_dist);
		for(int j = 1; j <= n; j++) maximum = max(maximum,t_dist[j]);
		if(maximum < minimum){
			minimum = maximum;
			index = i;
		}
		
	}
		
	printf("%d\n",index);
}

int main(){
	while(input()){
		solve();
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值