poj 2607

Fire Station
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 3846 Accepted: 1362

Description

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. 

Input

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.

Output

You are to output a single integer: 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.

Sample Input

1 6
2
1 2 10
2 3 10
3 4 10
4 5 10
5 6 10
6 1 10

Sample Output

5

题意: 输入n,m,接下来的n行每行一个数字,代表有消防站的节点编号。然后输入一些边(两端点和权值),现在要新建一个一个消防站,问这个消防站建在哪个点可以使所有点到离他最近消防站距离的最大值最小。如果有多个答案,输出最小的编号。wa点:初始时可以所有点都存在消防站,此时答案为1。

解法:最短路,先求出初始时所有点到最近的消防站的距离,存起来(为了方便叙述,我叫它实际距离),接下来枚举没有建消防站的点,对于每个“新建消防站的点”,算出所有没有消防站点到该点的距离,与实际距离相比较,我们新建一个数组(我把它叫做临时距离),如果算出的距离比实际距离小,临时距离存的是算出的值,否则存实际距离对应的值(可能我说的有点绕,但应该很好理解,我们要求的是没有消防站的点到最近的消防站的距离)。我们把临时距离里的最大值返回,便可以得到在当前点建消防站时:所有点到离他最近消防站距离的最大值。初始答案为1,只要返回值比之前的小便可以更新答案。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define INF 1e9
using namespace std;
int vis[600],head1[3600],dis[600],svis[600],ddis[600],juli[600];
struct edge{
    int u,v,w,next;
}e1[3600];
int cnt=1;
void readcase(int n,int m)
{
    for(int i=1;i<=n;i++){
        int node;
        scanf("%d",&node);
        vis[node]=1;
    }
     while(~scanf("%d%d%d",&e1[cnt].u,&e1[cnt].v,&e1[cnt].w)){
        e1[cnt].next=head1[e1[cnt].u];
        head1[e1[cnt].u]=cnt++;;
        e1[cnt].u=e1[cnt-1].v;
        e1[cnt].v=e1[cnt-1].u;
        e1[cnt].w=e1[cnt-1].w;
        e1[cnt].next=head1[e1[cnt].u];
        head1[e1[cnt].u]=cnt++;
    }
}
int spfa(int n,int m,int i)
{
    for(int j=1;j<=m;j++){
        dis[j]=INF;
    }
    memset(svis,0,sizeof(svis));
    dis[i]=0;
    queue<int> que;
    while(!que.empty()){
        que.pop();
    }
    que.push(i);
    svis[i]=1;
    while(!que.empty()){
        int d=que.front();
        que.pop();
        svis[d]=0;
        for(int j=head1[d];j;j=e1[j].next){
            if(dis[e1[j].v]>dis[d]+e1[j].w){
                dis[e1[j].v]=dis[d]+e1[j].w;
                if(!svis[e1[j].v]){
                    svis[e1[j].v]=1;
                    que.push(e1[j].v);
                }
            }
        }
    }
    int maxn=0;
    for(int j=1;j<=m;j++){
        if(!vis[j]){
            if(ddis[j]>dis[j]){
                juli[j]=dis[j];
            }
            else{
                juli[j]=ddis[j];
            }
        }
    }
    for(int j=1;j<=m;j++){
        if(!vis[j]){
            if(maxn<juli[j]){
                maxn=juli[j];
            }
        }
    }
    return maxn;
}
int compute(int n,int m,int i)
{
    int flag=0;
    if(!vis[i]){
        flag=1;
        vis[i]=1;
    }
    int s=spfa(n,m,i);
    if(flag){
        vis[i]=0;
    }
    return s;
}
void initial(int m)
{
    memset(head1,0,sizeof(head1));
    for(int i=1;i<=m;i++){
        ddis[i]=INF;
    }
}
void haha_spfa(int s,int m)
{
    ddis[s]=0;
    memset(svis,0,sizeof(svis));
    for(int j=1;j<=m;j++){
        dis[j]=INF;
    }
    queue<int> que;
    que.push(s);
    svis[s]=1;
    dis[s]=0;
    while(!que.empty()){
        int d=que.front();
        que.pop();
        svis[d]=0;
        for(int i=head1[d];i;i=e1[i].next){
            if(dis[e1[i].v]>dis[d]+e1[i].w){
                dis[e1[i].v]=dis[d]+e1[i].w;
                if(!svis[e1[i].v]){
                    svis[e1[i].v]=1;
                    que.push(e1[i].v);
                }
            }
        }
    }
    for(int i=1;i<=m;i++){
        if(!vis[i]){
            if(ddis[i]>dis[i]){
                ddis[i]=dis[i];
            }
        }
    }
}
int main()
{
    int n,m;
    int ansi;
    while(~scanf("%d%d",&n,&m)){
        cnt=1;
        ansi=1;
        memset(vis,0,sizeof(vis));
        initial(m);
        readcase(n,m);
        int ans=INF;
        for(int i=1;i<=m;i++){
            if(vis[i]){
                haha_spfa(i,m);
            }
        }
        for(int i=1;i<=m;i++){
            int ret=compute(n,m,i);
            if(ret<ans){
                ans=ret;
                ansi=i;
            }
        }
        printf("%d\n",ansi);

    }

    return 0;
}
/*
1 6
2
1 2 10
2 3 20
3 4 30
4 5 40
5 6 50
6 1 60
*/


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值