As the head of a city's emergency rescue team, you have a special national map. The map shows multiple scattered cities and some expressways connecting cities. The number of rescue teams in each city and the length of each expressway connecting the two cities are marked on the map. When other cities have emergency calls for you, your task is to lead your rescue team to catch up with the accident as soon as possible, and at the same time, call as many rescue teams as possible along the way.
Input format:
Input the first line to give four positive integers N, m, s and D, where N (2 ≤ N ≤ 500) is the number of cities. Incidentally, suppose that the number of cities is 0 ~ (N − 1); M is the number of expressways; S is the city number of the place of departure; D is the city number of the destination.
The second line gives N positive integers, where the ith number is the number of rescue teams in the ith City, and the numbers are separated by spaces. In the following M lines, each line gives the information of an expressway, namely: the length of city 1, city 2 and expressway, separated by spaces, and the numbers are integers and no more than 500. The input guarantees that the rescue is feasible and the optimal solution is unique.
Output format:
The first line outputs the number of shortest paths and the maximum number of rescue teams that can be convened. The second line outputs the city number passed in the path from S to D. Numbers are separated by spaces, and there must be no extra spaces at the end of the output.
Input example:
4 5 0 3 20 30 40 10 0 1 1 1 3 2 0 3 3 0 2 2 2 3 2
No blank lines at the end
Output example:
2 60 0 1 3
No blank lines at the end
#include <iostream> #define INF 0x3f3f3f3f #define MAXN 500 using namespace std; int n, m, s, d; int totalLen[MAXN]; //Record the shortest path from starting point S to city i int totalRescue[MAXN]; //Record the maximum number of rescue teams summoned from starting point S to city i int rescue[MAXN]; //Record the number of rescue teams in i city int Len[MAXN][MAXN]; //Record the path length between the two cities int cnt[MAXN]; //Record the number of shortest paths int pre[MAXN]; //Record the precursor of i City int vis[MAXN]{false}; //Mark whether to access void print(int u){ // Vertex = = starting point (recursive boundary, find the starting point) if(u == s){ cout << u; return; } // Find the precursor node recursive output (recursive) print(pre[u]); cout << " " << u; } void Dijkstra(int s){ totalLen[s] = 0; totalRescue[s] = rescue[s]; cnt[s] = 1; // Update N-1 times, source point updated for(int i = 0; i < n-1; i++){ int u, Min = INF; // Find nearest adjacency point for(int j = 0; j < n; j++) if(vis[j] == false && totalLen[j] < Min) u = j, Min = totalLen[j]; vis[u] = true; // The connected graph does not need to judge whether it is disconnected and exit for(int v = 0; v < n; v++){ // With the nearest adjacency point u as the intermediary, the vertex has not traversed the && path is shorter if(vis[v] == false && totalLen[v] > totalLen[u] + Len[u][v]){ // Update source point s to other vertex path length = s - > U + U - > V totalLen[v] = totalLen[u] + Len[u][v]; // Rescue team totalRescue[v] = totalRescue[u] + rescue[v]; // Number of shortest paths cnt[v] = cnt[u]; // Passing city pre[v] = u; } // Same path length else if(vis[v] == false && totalLen[v] == totalLen[u] + Len[u][v]){ // The shortest path is not unique cnt[v] += cnt[u]; // More rescue teams if(totalRescue[v] < totalRescue[u] + rescue[v]){ totalRescue[v] = totalRescue[u] + rescue[v]; pre[v] = u; } } } } }; int main() { // Initialization path length and city shortest path fill(*Len, *Len + MAXN * MAXN, INF); fill(totalLen, totalLen + MAXN, INF); cin >> n >> m >> s >> d; // Read the number of rescue teams and path length for(int i = 0; i < n; i++){ cin >> rescue[i]; } for(int i = 0; i < m; i++){ int c1, c2, len; cin >> c1 >> c2 >> len; Len[c1][c2] = Len[c2][c1] = len; } Dijkstra(s); // Output the shortest path and the maximum number of rescue teams cout << cnt[d] << " " << totalRescue[d] << endl; // Export route City print(d); }
cnt[to] += cnt[pass];
Think about why you want to accumulate the previous paths here. If there is no initialization, all CNTs are 0. So add this code to the judgment of the update path length and the same path to see what happens.
cout << totalLen[to] << " " << pass << " " << to << " " << cnt[pass] << " " << cnt[to] << endl;
You can see the update from source point 0 to end point 3. There are 0 - > 3 and 1 - > 3 with the same path length, both of which are the first 3. At this time, there are two paths to destination 3, and if other points pass through 3 to other destinations, 2 will be added. The following nodes are similar, so you can know why + =.