PAT 1003 Emergency (25) [Dijkstra算法] HERODING的PAT之路

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条路,每个城市有救援⼩组,所有的边的边权已知。给定起点和终点,求从起点到终点的最短路径条数以及最短路径上的救援⼩组数⽬之和。如果有多条就输出点权(城市救援⼩组数⽬)最⼤的那个。

解题思路:
这道题目是经典的Dijkstra的改动形式,在原来的基础上添加了一些约束,即文中提到要求解最大救援队数目以及最短路径数目,首先我们定义好所需要的数据结构(代码中已经详细标注),接着我们初始化数据,并把起始城市的数据进行标注,接着我们遍历所有的城市,找到未放入最短路径并且dis最短的城市,以此城市为中心,对其他未遍历过的城市进行更新,那多路径怎么处理呢,当面对已经在最短路径中的城市,以及已经在最短路径上但没有访问过的城市,则num[v] = num[v] + num[index]即可更新多路径,代码如下:

#include<iostream>
#include<algorithm>

using namespace std;

// 定义无穷远
const int inf = 99999999;
// 定义城市数,路径数,起始城市,要拯救的城市
int n, m, c1,c2;
// 分别代表边的权重,每座城市救援队数目,起始点到第i个点的最短距离,起始点到第i个点的最短路径数目,起始点到第i个城市救援队总数
int edge[510][510], weight[510], dis[510], num[510], w[510];
// 初始化城市,都没有访问过
bool visit[510] = {
    
    false};

int main() {
    
    
    cin >> n >> m >> c1 >> c2;
    for(int i = 0; i < n; i ++) {
    
    
        cin >> weight[i];
    }
    fill(edge[0], edge[0] + 510 * 510, inf);
    fill(dis, dis + 510, inf);
    int a, b, c;
    for(int i = 0; i < m; i ++) {
    
    
        cin >> a >> b >> c;
        edge[a][b] = edge[b][a] = c;
    }
    dis[c1] = 0;
    w[c1] = weight[c1];
    num[c1] = 1;
    // 遍历所有的城市
    for(int i = 0; i < n; i ++) {
    
    
        int index = -1, min = inf;
        for(int j = 0; j < n; j ++) {
    
    
            if(visit[j] == false && dis[j] < min) {
    
    
                index = j;
                min = dis[j];
            }
        }
        if(index == -1) break;
        // 将该城市加入到最短路径中
        visit[index] = true;
        for(int v = 0; v < n; v ++) {
    
    
            // 更新
            if(visit[v] == false && edge[index][v] != inf) {
    
    
                // 更新路径,最短路径数,目前总救援队数
                if(dis[index] + edge[index][v] < dis[v]) {
    
    
                    dis[v] = dis[index] + edge[index][v];
                    num[v] = num[index];
                    w[v] = w[index] + weight[v];
                } else if(dis[index] + edge[index][v] == dis[v]) {
    
    
                    // 更新最短路径数,目前总救援队数
                    num[v] = num[index] + num[v];
                    if(w[index] + weight[v] > w[v]) {
    
    
                        w[v] = w[index] + weight[v];
                    }
                }
            }
        }
    }
    cout << num[c2] << " " << w[c2];
    return 0;
}

猜你喜欢

转载自blog.csdn.net/HERODING23/article/details/114198301
今日推荐