Poj 1122 FDNY to the Rescue

题目描述:
纽约消防局一直以他们对纽约市火警的反应时间而自豪,但是他们还想让反应时间更快。请
帮助他们改进他们的反应时间。他们想确保总局指挥中心知道一旦有火警,哪个消防站离火警位
置最近。你被雇来编写这个软件,以维护消防局的自豪。给定火警位置、所有消防站的位置、街
道交叉路口、通过每条连接交叉路口之间道路所需的时间,该程序必须根据这些信息计算每个消
防站到达一个指定火警位置所需时间。这些时间必须按从小到大的顺序进行排序,这样指挥中心

就可以选择一个最近的消防站、并派出足够多的消防队员、携带足够多的设备去灭火。


输入描述:
每个测试数据的格式如下:
第1 行为一个整数N(N<20),表示城市中交叉路口的数目。
第2~N+1 行:为N×N 的矩阵,矩阵中的元素用一个或多个空格隔开。矩阵中的元素tij,
表示从第i 个交叉路口到第j 个交叉路口所需的时间(分钟),如果tij 值为-1,则表示从第i 个交叉
路口到第j 个交叉路口没有直接路径。
第N+2 行首先是一个整数n(n≤N),代表火警位置所在的交叉路口;然后有一个或多个整数,
表示消防站所处的交叉路口。
注意:
1) 行和列的序号都是从1~N;
2) 测试数据中所有数据都是整数;
3) 测试数据保证每个消防站都是可以到达火警位置的;
4) 消防站到火警的距离为消防站所处的交叉路口到火警位置所在的交叉路口的距离。
输出描述:
每个测试数据的输出格式如下:
第1 行:列表的标题行,内容和格式如样例输出所示。
从第2 行开始每一行描述了一个消防站的信息,这些信息按消防站到达火警位置所需时间从
小到大排列。这些信息包括:消防站的位置(初始位置)、火警位置(目标位置)、所需时间以及
最短路径上的每个交叉路口。
注意:
1) 列与列之间用tab 键隔开;
2) 如果多个消防站到达的时间一样,则这些消防站之间的输出顺序任意;
3) 如果从某个消防站到火警位置所需的时间为最短时间的路径不止一条,则输出任意一条;
4) 如果火警位置和某个消防站的位置恰好是同一个交叉路口,则输出时,该消防站的输出行
中,初始位置和目标位置是同一个交叉路口,所需时间为0,最短路径上只有一个交叉路口序号,

就是火警位置的序号。


Sample Input

6 
0  3  4 -1 -1 -1 
-1 0  4  5 -1 -1 
2  3  0 -1 -1  2 
8  9  5  0  1 -1 
7  2  1 -1  0 -1 
5 -1  4  5  4  0 
2  4  5  6 
In the above input the last line indicates that "2" is the location of the fire and "4", "5" and "6" are the intersections where fire stations are located. 

Sample Output

Org	Dest	Time	Path
5	2	2	5	2
4	2	3	4	5	2
6	2	6	6	5	2


题目要求很周全,除了求最短路径,还需要求出路径,需要dijkstra+细心。需要注意的是:由样例得知:此图不是无向图。

所以利用的是反向dijkstra,多起点到终点。

个人觉得这些天看图论还是很有收获的,还需多多练习.......~~

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#define MAX 50
#define INF 0x7FFFFFFF
# define eps 1e-5
using namespace std;
int edge[MAX][MAX],visit[MAX],index[MAX];//边的信息,访问,记录路径
int n,m,v0;
struct Dist
{
    int tim;//路径时间
    int vis;//此点是否为消防点
    int num;//编号
} dist[MAX];

bool cmp(Dist a,Dist b)
{
    return a.tim < b.tim;
}
void print(int u0)//打印路径结果
{
    printf("%d\t",u0);//本来觉得会PE的,不过算POJ不严格..就AC了
    if(index[u0] != -1)
        print(index[u0]);
}

void dijkstra(int u0)//模版
{
    int i,j,v;
    memset(visit,0,sizeof(visit));
    visit[u0] = 1;
    index[u0] = -1;
    for(j=0; j<n-1; j++)//n-1条路径
    {
        int min = INF;
        for(i=1; i<=n; i++)
        {
            if(!visit[i] && min > dist[i].tim)
            {
                min = dist[i].tim;
                v = i;
            }
        }
        visit[v] = 1;
        for(i=1; i<=n; i++)
        {
            if(!visit[i] && edge[i][v] != INF && edge[i][v] + dist[v].tim < dist[i].tim)
            {
                dist[i].tim = edge[i][v] + dist[v].tim;
                index[i] = v;//点i的前导为点v
            }
        }
    }
}

int main()
{
    int i,j,u0,res[MAX],t = 0;
    char x[1000];
    scanf("%d",&n);
    for(i=1; i<=n; i++)//构图
        for(j=1; j<=n; j++)
        {
            scanf("%d",&edge[i][j]);
            if(edge[i][j] == -1)
                edge[i][j] = INF;
        }
    scanf("%d",&v0);
    for(i=1; i<=n; i++)//初始化dist数组和路径
    {
        dist[i].tim = edge[i][v0];
        dist[i].vis = 0;
        dist[i].num = i;
        index[i] = v0;
    }
    gets(x);//输入的最后一部分只想到这样输入
    int len = strlen(x);
    for(i=0; i<len; i++)//有消防的点做出标记
    {
        if(x[i]>='0' && x[i] <= '9')
        {
            res[t] = x[i] - '0';
            dist[res[t]].vis = 1;
        }
    }
    dijkstra(v0);
    sort(dist+1,dist+n+1,cmp);
    printf("Org\tDest\tTime\tPath\n");
    for(i=1; i<=n; i++)
    {
        if(dist[i].vis == 1)//输出有消防的点的信息
        {
            printf("%d\t%d\t%d\t",dist[i].num,v0,dist[i].tim);
            print(dist[i].num);
            printf("\n");
        }
    }
    return 0;
}


你可能感兴趣的:(Poj 1122 FDNY to the Rescue)