天天看點

PAT-A-1003 Emergency (25分) C/C++實作(最短路徑,Dijkstra算法)

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, C1 and C2 - 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 c1, c2 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 C1 to C2.

Output Specification:

For each test case, print in one line two numbers: the number of different shortest paths between C1 and C2 , 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

  • 題目大意:

    給出編号為0 ~ n - 1 的n個城市,城市之間有m條路,每條路的兩個端點和長度已知;每個城市有一些救援小組,數目已知。現給定起點和終點,求從起點到終點最短路徑的條數,以及在最短路徑上可以到達的救援小組數目之和的最大值。

  • 思路:
    1. 用Dijkstra算法計求得最短路徑;
    2. 注意最後需要輸出的是最短路徑的數量而非距離;
#include <iostream>
#include <vector>
#include <algorithm>
#define INF 0xfffffff
using namespace std;
struct Node
{
    int next, dis; 
};
vector <Node> city[500]; //記錄相鄰城市之間的路程
int num_rescue[500];//記錄每個城市的救援組的數量
int min_dist[500];//記錄起點到各個城市的最短距離
int num_mindist_route[500] = {0};//記錄起點到各個城市的距離最短路徑的條數
int max_rescue[500] = {0};//記錄起點到各個城市可以召集的最多救援人數
bool mark[500] = {0};
int n, m, s, d;
void Dijkstra(int newp)
{
    if (newp == d)
    {
        return;
    }
    for (int i = 0; i < city[newp].size() ; i++) //周遊與目前點直接相鄰的點,更新最短路徑的長度、數量,和最大救援隊數目
    {
        int next = city[newp][i].next, dis = city[newp][i].dis;
        if (mark[next] == true)
        {
            continue;
        }
        if (min_dist[next] == -1 || min_dist[next] > min_dist[newp] + dis)
        {
            min_dist[next] = min_dist[newp] + dis;
            num_mindist_route[next] = num_mindist_route[newp];
            max_rescue[next] = max_rescue[newp] + num_rescue[next];
        }
        else if (min_dist[next] == min_dist[newp] + dis)
        {
            num_mindist_route[next] += num_mindist_route[newp]; //如果距離相等,則起點到目前城市的距離最短路徑的條數為兩者之和
            max_rescue[next] = max(max_rescue[next], max_rescue[newp] + num_rescue[next]);
        }
    }
    int mindis = 0xfffffff, index;
    for (int i = 0; i < n; i++) //在剩餘未被标記的點中,選出與起點距離最近的點
    {
        if (mark[i] == true || min_dist[i] == -1)
        {
            continue;
        }
        if (min_dist[i] < mindis)
        {
            mindis = min_dist[i];
            index = i;
        }
    }
    mark[index] = true;
    Dijkstra(index);
}
int main()
{
    cin >> n >> m >> s >> d;
    for (int i = 0; i < n; i++)
    {
        cin >> num_rescue[i];
    }
    for (int i = 0; i < m; i++)
    {
        int a, b;
        Node temp;
        cin >> a >> b >> temp.dis;
        temp.next = b;
        city[a].push_back(temp);
        temp.next = a;
        city[b].push_back(temp);
    }
    fill(min_dist, min_dist + n, -1);
    mark[s] = true, min_dist[s] = 0, max_rescue[s] = num_rescue[s], num_mindist_route[s] = 1;
    Dijkstra(s);
    cout << num_mindist_route[d] << ' ' << max_rescue[d];
    return 0;
}