PAT A 1003(甲级)

这是一道关于紧急救援路径规划的问题,需要从C1城市出发到达C2城市,目标是找到最短路径并沿途召集最多的救援队伍。采用Dijkstra算法求解最短路径,通过比较不同路径上的救援队伍数量来选择最优解。代码实现中,若新路径与当前路径相同则比较救援队伍数量,以确定最佳路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1003 Emergency(25 分)

作者: CHEN, Yue

单位: 浙江大学

时间限制: 400 ms

内存限制: 64 MB

代码长度限制: 16 KB

As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.

Input Specification:

Each input file contains one test case. For each test case, the first line contains 4 positive integers: N (≤500) - the number of cities (and the cities are numbered from 0 to N−1), M - the number of roads, C​1​​ and C​2​​ - the cities that you are currently in and that you must save, respectively. The next line contains N integers, where the i-th integer is the number of rescue teams in the i-th city. Then M lines follow, each describes a road with three integers c​1​​, c​2​​ and L, which are the pair of cities connected by a road and the length of that road, respectively. It is guaranteed that there exists at least one path from C​1​​ to C​2​​.

Output Specification:

For each test case, print in one line two numbers: the number of different shortest paths between C​1​​ and C​2​​, and the maximum amount of rescue teams you can possibly gather. All the numbers in a line must be separated by exactly one space, and there is no extra space allowed at the end of a line.

Sample Input:

5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1

Sample Output:

2 4

 


 

N个城市 ,M条道路,从C1到C2,首先保证路径最短,其次要保证救援队伍的数目最大,然后输出路径数量。

 

我们首先可以确定使用dijkstra算法计算最短路,然后再选择路径的位置增加题目额外条件,如果下一条路径比当前路径短,则选择最短路,并计算救援队伍数量和路径数量。如果新路径与当前路径相同,则比较两者经过的救援队伍数量多少来进行选择,同时路径+1。

 

也就是代码中的这一段:

if(!vis[j] && G[minv][j] != INF) {
    if(G[minv][j] + d[minv] < d[j]) {
        d[j] = G[minv][j] + d[minv];
        road[j] = road[minv];
        maxres[j] = maxres[minv] + resnum[j];
    } else if(G[minv][j] + d[minv] == d[j]) {
        road[j] += road[minv];
        if(maxres[j] < maxres[minv] + resnum[j]) {
            maxres[j] = maxres[minv] + resnum[j];
        }
    }
}

 


 

AC代码:

//    2018年8月28日11:16:35
//    这个题出的一点也不好,因为使用暴力破解的方法也同样可以解题,使用数学推倒可以优化解题过程 算法笔记中有更好的方法
#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn = 510;
const int INF = 1000000000;

int n, m, c1, c2;
bool vis[maxn] = {false};
int resnum[maxn], G[maxn][maxn], d[maxn], road[maxn], maxres[maxn];

void dijkstra(int);

int main() {
    fill(G[0], G[0] + maxn * maxn, INF);
    scanf("%d%d%d%d", &n, &m, &c1, &c2);
    for(int i = 0; i < n; ++i) {
        scanf("%d", resnum + i);
    }

    for(int i = 0; i < m; ++i) {
        int a, b, rl;
        scanf("%d%d%d", &a, &b, &rl);
        G[a][b] = rl;
        G[b][a] = rl;
    }

    dijkstra(c1);

    printf("%d %d\n", road[c2], maxres[c2]);

    return 0;
}

void dijkstra(int c1) {
    fill(d, d + maxn, INF);
    d[c1] = 0;
    maxres[c1] = resnum[c1];
    road[c1] = 1;

    for(int i = 0; i < n; ++i) {
        if(vis[c2]) {
            return ;
        }
        int minv = -1, minl = INF;
        for(int j = 0; j < n; ++j) {
            if(!vis[j] && d[j] < minl) {
                minl = d[j];
                minv = j;
            }
        }

        if(minv == -1) {
            return ;
        }
        vis[minv] = true;
        for(int j = 0; j < n; ++j) {
            if(!vis[j] && G[minv][j] != INF) {
                if(G[minv][j] + d[minv] < d[j]) {
                    d[j] = G[minv][j] + d[minv];
                    road[j] = road[minv];
                    maxres[j] = maxres[minv] + resnum[j];
                } else if(G[minv][j] + d[minv] == d[j]) {
                    road[j] += road[minv];
                    if(maxres[j] < maxres[minv] + resnum[j]) {
                        maxres[j] = maxres[minv] + resnum[j];
                    }
                }
            }
        }
    }
}

 


 

如有错误,欢迎指摘。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值