1003 Emergency【PAT (Advanced Level) Practice】

1003 Emergency【PAT (Advanced Level) Practice】

Original question link:Preview question details - 1003 Emergency (pintia.cn)

1.Original text of the title

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 N N ( ≤ 500 \and 500500) - the number of cities (and the cities are numbered from 0 to N − 1 N-1 N1), M M M - the number of roads, C 1 C_1 C1 and C 2 C_2 C2 - the cities that you are currently in and that you must save, respectively. The next line contains N N N integers, where the i i i-th integer is the number of rescue teams in the i i i-th city. Then M M M lines follow, each describes a road with three integers c 1 c_1 c1, c 2 c_2 c2 and L L 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 C_1 C1 to C 2 C_2 C2.

Output Specification:

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

2. Title translation

As the leader of a city's emergency rescue team, you are provided with a special map of your country. The map shows a few scattered cities connected by a few roads. The map is marked with the number of rescue teams in each city and the length of roads between any pair of cities. When you receive an emergency call from another city, your job is to lead your team to that location as quickly as possible while summoning as much aid as possible along the way.

Input specifications:

Each input file contains one test case. For each test case, the first line contains 4 positive integers: N N N( ≤ 500 \le 500500) - the number of cities (city numbers from 0 to N − 1 N-1 N1), M M M - Road quantity, C 1 C_1 C1sum C 2 C_2 C2 - The city you are currently in and the city you must save. The next line contains N N Ninteger, the first i i iAn integer is the first i i Number of rescue teams in i cities. Then M M M rows, each row describes a road and contains three integers c 1 c_1 c1 c 2 c_2 c2sum L L L, respectively, are the city pairs connected by a road and the length of the road. Ensure that there is at least one from C 1 C_1 C1to C 2 C_2 C2path of.

Output specification:

For each test case, print two numbers on one line: C 1 C_1 C1sum C 2 C_2 C2Different between the number of shortest paths, and the maximum number of rescue teams you can possibly collect. All numbers in a line must be separated by a space, and there must be no extra spaces at the end of the line.

Example 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

Example output:

2 4

3. Problem-solving ideas

3.1 Question analysis

Calculate how many different shortest paths there are to reach the target city, and among these paths, what is the maximum number of rescue teams that can be summoned.

Enter the number of cities, number of roads, starting city, target city, number of rescue teams in each city, and length of roads between cities.

Output the number of shortest paths and the maximum number of rescue teams that can be summoned along these paths.

3.2 Basic ideas

Use Dijkstra's algorithm to solve the single-source shortest path problem, where the goal is to find the shortest path from a starting point to all other vertices. In this problem, in addition to finding the number of shortest paths, it is also necessary to calculate the maximum number of rescue teams in the cities passed by the shortest path.

3.3 Detailed steps

  1. Initialization: Initializes the adjacency matrix and correlation array of the graph. Set the shortest path from the starting point to itself to 0, and set the shortest path length to infinity for all other vertices. At the same time, a collection (usually implemented using a priority queue or a min-heap) is maintained to store vertices for which the shortest path has not been determined.

  2. Read input: Read the number of cities (n), the number of roads (m), the starting point (s), the target point (d), and each The relationship between the number of rescue teams and road connections in a city.

  3. Dijkstra's algorithm: Use Dijkstra's algorithm to calculate the number of shortest paths from the starting point to the target point and the maximum number of rescue teams. At each step, the vertex with the shortest current path is selected, the path lengths of its adjacent vertices are updated, and the number of shortest paths and the maximum number of rescue teams are maintained.

  4. Output results: Output the number of shortest paths and the maximum number of rescue teams.

4. Reference answer

#include <stdio.h>

#define MAXN 500
#define inf 1000000000//inf表示无穷大,即表示两城市之间无直接道路
typedef int elem_t;

//mat[MAXN][MAXN]: 二维数组,表示城市之间的道路长度的邻接矩阵。mat[i][j]存储了城市i到城市j之间的道路长度。
//min[MAXN]: 一维数组,表示从起点到每个城市的当前最短路径长度。min[i]存储了从起点到城市i的当前最短路径长度。
//pre[MAXN]: 一维数组,表示每个城市在最短路径中的前驱城市。pre[i]存储了在最短路径中城市i的前驱城市。
//store[MAXN]: 一维数组,表示每个城市的救援队数量。store[i]存储了城市i的救援队数量。

elem_t s, mat[MAXN][MAXN], min[MAXN], pre[MAXN], store[MAXN];

// 初始化图的邻接矩阵
void initialize(int n){
    
    
    int i, j;

    for (i = 0; i < n; i++)
        for (j = 0; j < n; j++)
            mat[i][j] = inf;//初始化所有城市距离无穷大,即无直接道路
}

// 读取城市的救援队信息和道路的长度
void read_store_matrix(int n, int m) {
    
    
    int i, j, k;

    // 初始化图的邻接矩阵
    for (i = 0; i < n; i++)
        for (j = 0; j < n; j++)
            mat[i][j] = inf;

    // 读取每个城市的救援队数量
    for (i = 0; i < n; i++)
        scanf("%d", &store[i]);

    // 读取道路的连接关系和长度
    for (k = 0; k < m; k++) {
    
    
        scanf("%d %d", &i, &j);
        scanf("%d", &mat[i][j]);
        mat[j][i] = mat[i][j];  // 由于是无向图,道路是双向的,因此对称赋值
    }
}


// 使用Dijkstra算法计算最短路径和最大救援队数量
void dijkstra(int n, elem_t d){
    
    
    int v[MAXN], cnt[MAXN], jb[MAXN];
    int i, j, k;

    // 初始化数组
    for (i = 0; i < n; i++)
        min[i] = inf, v[i] = 0, cnt[i] = 0, jb[i] = store[i], pre[i] = -1;
    
    // 起点的路径长度为0,起点被标记为已确定最短路径
    cnt[s] = 1;

    for (min[s] = 0, j = 0; j < n; j++){
    
    
        // 选择当前路径最短的顶点
        for (k = -1, i = 0; i < n; i++)
            if (!v[i] && (k == -1 || min[i] < min[k]))
                k = i;

        // 标记当前顶点为已确定最短路径
        v[k] = 1;

        // 更新当前顶点的邻接顶点的路径长度
        for (i = 0; i < n; i++)
            if (!v[i]) {
    
    
                if (min[k] + mat[k][i] < min[i]) {
    
    
                    // 更新最短路径和最大救援队数量
                    min[i] = min[k] + mat[pre[i] = k][i];
                    cnt[i] = cnt[k];
                    jb[i] = jb[k] + store[i];
                }
                else if (min[k] + mat[k][i] == min[i]) {
    
    
                    // 如果有多条最短路径,累加路径数量和更新最大救援队数量
                    cnt[i] += cnt[k];
                    if (jb[k] + store[i] > jb[i]) 
                        jb[i] = jb[pre[i] = k] + store[i];
                }
            }
    }

    // 输出最短路径数量和最大救援队数量
    printf("%d %d\n", cnt[d], jb[d]);
}

int main(){
    
    
    int n, m;
    elem_t d;

    // 读取输入
    scanf("%d %d %d %d", &n, &m, &s, &d);
    
    // 初始化图和读取城市信息及道路长度
    initialize(n);
    read_store_matrix(n, m);

    // 运行Dijkstra算法
    dijkstra(n, d);

    return 0;
}

5.Knowledge expansion

Dijkstra's algorithm(Dijkstra)

Dijkstra's algorithm(Dijkstra) is the shortest path algorithm from one vertex to the remaining vertices. It solves the shortest path problem in weighted graphs. The main feature of Dijkstra's algorithm is that it starts from the starting point, adopts the strategy of greedy algorithm, and traverses the adjacent nodes of the unvisited vertices closest to the starting point each time until it extends to the end point.

DijkstraThe algorithm is a greedy algorithm for solving the single-source shortest path problem. This algorithm finds the shortest path from the starting point to all other vertices step by step. The specific steps are as follows:

  1. Initialization: Sets the shortest path length from the starting point to itself to 0, and sets the shortest path length to infinity for all other vertices. At the same time, a collection (usually implemented using a priority queue or a min-heap) is maintained to store vertices for which the shortest path has not been determined.

  2. Select vertices: Select a vertex from which the shortest path to the starting point is the known minimum.

  3. Update path: For the selected vertex, traverse all its adjacent vertices and update the path length from the starting point to these adjacent vertices. If the path to an adjacent vertex through the currently selected vertex is shorter than the known shortest path, the shortest path and path length are updated.

  4. Mark determined: Mark the currently selected vertex as the determined shortest path and remove it from the set of undetermined shortest paths.

  5. Repeat: Repeat steps 2-4 until all vertices are marked as shortest path determined, or the set is empty.

DijkstraThe characteristic of the algorithm is that it is very effective for graphs with non-negative weights. At each step, it selects the vertex with the shortest current path, ensuring that the resulting path is the global shortest path. However, if there are negative-weighted edges in the graph, the Dijkstra algorithm may produce erroneous results, so for graphs containing negative-weighted edges, the Bellman-Ford algorithm is more suitable.

Bellman-Ford algorithm(Bellman-Ford)

Bellman-Ford algorithm(Bellman-Ford) is an algorithm used to solve the single-source shortest path problem. It is different from the Dijkstra algorithm. The Bellman-Ford algorithm can handle graphs with negative weight edges, but the disadvantage is that the time complexity is too high. The basic idea is to gradually approach the shortest path by continuously relaxing the edge weights. The specific steps are as follows:

  1. Initialization: Sets the shortest path length from the starting point to itself to 0, and sets the shortest path length to infinity for all other vertices. At the same time, an array is initialized to record the predecessor vertices of each vertex.

  2. Relaxed edges: For each edge in the graph, continuously try to see whether a shorter path can be obtained through the current path. If possible, update the shortest path length and predecessor vertex.

  3. Repeat: Repeat the process of relaxing edges until the shortest path length without vertices changes.

  4. Detect negative weight loops: If there are still edges that can be relaxed in a certain round of relaxation operation, it means that there is a negative weight loop in the graph. Because negative weight loops can continuously reduce the path length, the shortest path cannot be determined.

The Bellman-Ford algorithm is suitable for graphs containing negative weight edges, but since its time complexity is O(VE), where V is the number of vertices, < /span> algorithm is more efficient. algorithm, the performance is relatively poor. When the graph is sparse, the of the E is the number of edges. Compared with DijkstraO((V+E)logV)Dijkstra

Guess you like

Origin blog.csdn.net/weixin_40171190/article/details/134745792