Fire Station

描述
A city is served by a number of fire stations. Some residents have complained that the distance from their houses to the nearest station is too far, so a new station is to be built. You are to choose the location of the fire station so as to reduce the distance to the nearest station from the houses of the disgruntled residents. 

The city has up to 500 intersections, connected by road segments of various lengths. No more than 20 road segments intersect at a given intersection. The location of houses and firestations alike are considered to be at intersections (the travel distance from the intersection to the actual building can be discounted). Furthermore, we assume that there is at least one house associated with every intersection. There may be more than one firestation per intersection.

输入
The first line of input contains two positive integers: f,the number of existing fire stations (f <= 100) and i, the number of intersections (i <= 500). The intersections are numbered from 1 to i consecutively. f lines follow; each contains the intersection number at which an existing fire station is found. A number of lines follow, each containing three positive integers: the number of an intersection, the number of a different intersection, and the length of the road segment connecting the intersections. All road segments are two-way (at least as far as fire engines are concerned), and there will exist a route between any pair of intersections.

Subsequent test cases are separated with a single blank line.

The number of test cases are less than 200.
输出
You are to output a single integer for each test case: the lowest intersection number at which a new fire station should be built so as to minimize the maximum distance from any intersection to the nearest fire station.
样例输入
1 6
2
1 2 10
2 3 10
3 4 10
4 5 10
5 6 10
6 1 10
样例输出

5


题意:有f个消防站已经建在十字路口,n个十字路口,每个路口附近都有居民居住,有些居民抗议他离最近的消防站太远了,所以现在需要再建

一个消防站,使得所有居民最近消防站最远的距离最近(有点拗口,认真读懂吧)。

题解:由于f<=100,n<=500,所以感觉可以直接算,首先要求出居民最近消防站的距离,这个就可以转换成已有的消防站到居民的距离中最小,很容易想到的是直接对所有消防站求一次最短路每个点取所有最短路中最小的,这样就可以知道所有居民最近的消防站的最远距离(求一次最大值),然后就可以枚举所有没有消防站的十字路口求最短路,和前面求出所有居民最近的消防距离再取最小值(这样就假设消防站建在此处),看最大值是否比没建此消防站的距离小,距离小就可以更新,取距离最小的那个十字路口。这里还需要注意的是输入路径时是以一个空行结束。这样是可以过poj和zoj的题目,但是在nyoj中还是超时了,其实可以发现在求最短路取最小值时是不需要每次去初始化,因为取的就是最小值,如果距离比当前值要大,就没必要更新,所以在求已有的消防站到居民的距离中最小的时候只需要更新一次,这样其实可以减少很多计算量,而且在这里用spfa比较好,用Dijkstra时不要用优先队列,因为使用优先队列时不一定是将最小的加入队列的,所以会导致超时,在后面新建消防站也用这种方法就可以了,反正都是求的最小值,不过注意这个时候不要将原来数据覆盖了。

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <utility>
#include <map>
#include <set>
#include <queue>
#include <vector>
#include <iostream>
#include <stack>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-6
#define CLR( a, v ) memset ( a, v, sizeof ( a ) )
#define LL long long
#define DBUG printf ( "here!!!" )
#define rep( i, a, b ) for ( int i = ( a ); i < ( b ); i ++ )
#define PB push_back
#define ULL unsigned long long
#define PI acos ( -1.0 )
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1 | 1
#define lowbit( x ) ( ( x )&( -x ) )
#define CASE int T; scanf ( "%d", &T ); for ( int cas = 1; cas <= T; cas ++ )
#define ALL( x ) x.begin ( ), x.end ( )
#define INS( x ) x, x.begin ( )
typedef pair < int, int > Pii;
typedef pair < double, double > Pdd;
typedef set < int > Set;
const int maxn = 505, N = maxn*20;
int read_int ( )
{
    int res = 0;
    int ch;
    while ( ( ch = getchar ( ) ) && ! ( ch >= '0' && ch <= '9' ) )
    {
        if ( ch == -1 )
            return -1;
    }
    while ( ch >= '0' && ch <= '9' )
    {
        res = res*10+( ch-'0' );
        ch = getchar ( );
    }
    return res;
}
struct node
{
    int to, len;
    node ( ) { }
    node ( int v, int l ) : to ( v ), len ( l ) { }
};
int d[maxn], mn[maxn], tmp[maxn];
int head[N], nxt[N], pos, n;
node mp[N];
bool has[maxn], inq[maxn];
void addEdge ( int u, node t )
{
    mp[pos] = t;
    nxt[pos] = head[u];
    head[u] = pos ++;
}
void spfa ( int s )
{
    queue < int > q;
    d[s] = 0;
    q.push ( s );
    CLR ( inq, false );
    while ( ! q.empty ( ) )
    {
        int u = q.front ( );
        q.pop ( );
        inq[u] = false;
        for ( int i = head[u]; ~ i; i = nxt[i] )
        {
            int val = mp[i].len, v = mp[i].to;
            if ( d[v] > d[u]+val )
            {
                d[v] = d[u]+val;
                if ( inq[v] == false )
                {
                    inq[v] = true;
                    q.push ( v );
                }
            }
        }
    }
}
char str[maxn];
void solve ( )
{
    int f, u, v, w, sta;
    while ( ~ scanf ( "%d%d", &f, &n ) )
    {
        CLR ( has, false );
        pos = 0;
        CLR ( head, -1 );
        for ( int i = 0; i < f; i ++ )
        {
            scanf ( "%d", &sta );
            has[ sta ] = true;
        }
        getchar ( );
        while ( gets ( str ) != '\0' && str[0] != '\0' )
        {
            u = v = w = -1;
            int len = strlen ( str );
            for ( int i = 0; i < len; )
            {
                if ( str[i] >= '0' && str[i] <= '9' )
                {
                    int val = 0;
                    while ( i < len && str[i] >= '0' && str[i] <= '9' )
                    {
                        val = val*10+( str[i]-'0' );
                        i ++;
                    }
                    if ( u == -1 )
                        u = val;
                    else if ( v == -1 )
                        v = val;
                    else
                        w = val;
                }
                else
                    i ++;
            }
            addEdge ( u, node ( v, w ) );
            addEdge ( v, node ( u, w ) );
        }
        CLR ( d, 0x3f );    //只初始化一次减少计算量
        for ( int i = 1; i <= n; i ++ )
        {
            if ( has[i] == false )
                continue ;
            spfa ( i );
        }
        int ans = 0, pos = 1;
        for ( int i = 1; i <= n; i ++ )
        {
            mn[i] = d[i];   //保存中间值
            ans = max ( ans, mn[i] );
        }
        for ( int i = 1; i <= n; i ++ )
        {
            if ( has[i] )
                continue ;
            for ( int j = 1; j <= n; j ++ )
                d[j] = mn[j];
            spfa ( i );
            int mx = 0;
            for ( int j = 1; j <= n; j ++ )
                mx = max ( d[j], mx );
            if ( ans > mx )
            {
                ans = mx;
                pos = i;
            }
        }
        printf ( "%d\n", pos );
    }
}
int main ( )
{
    solve ( );
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值