[Luogu] P1608 path statistics

Posted by gio2k on Sun, 20 Feb 2022 05:44:27 +0100

Title address:

https://www.luogu.com.cn/problem/P1608

Title Description:
The staff quality of "RP restaurant" is not general. After calculating the same phone number, they are ready to let HZH and TZY deliver fast food. They draw a map of the city they live in. It is known that on their map, there are N N At present, they are in N places 1 1 1, and the place of delivery is marked as N N N's town. (a little nonsense) besides, I also know that these roads are one-way, from the small town I I I to J J J costs D [ I , J ] D[I,J] D[I,J], in order to deliver fast food to customers more efficiently and quickly, they want to take a route from the town 1 1 1 to the town N N N is the least expensive road, but before they set out, they ran into FYY, who was angry because of the traffic jam on the road. They were deeply inspired and couldn't only know one route, just in case... So they invited FYY to study the next question: how many paths are the least expensive?

Input format:
The first line of the input file is the number separated by two spaces N N N, E E E. Information indicating how many towns and sides there are in this map. below E E Line E, three numbers per line I I I, J J J, C C C. Indicates from I I I town to J J J town is connected by road and costs C C C (note that the edge information provided by the data may be repeated, but it is guaranteed I ≠ J , 1 ≤ I , J ≤ N I\ne J,1 \le I, J≤N I​=J,1≤I,J≤N).

Output format:
The output file contains two numbers, which are the total number of least cost and least cost paths. Two different shortest path schemes require that the path length is the same (both are the shortest path length) and at least one edge does not coincide. If City N N If N cannot be reached, only one No answer is output.

Data range:
about 30 30% 30 data N ≤ 20 N≤20 N≤20; about 100 100% 100 data 1 ≤ N ≤ 2000 , 0 ≤ E ≤ N × ( N − 1 ) , 1 ≤ C ≤ 10 1≤N≤2000, 0≤E≤N×(N−1),1≤C≤10 1≤N≤2000,0≤E≤N×(N−1),1≤C≤10.

Note that the information of the "edge" of this question may be repeated. It means that the repeated edge is calculated according to the shortest one, and the other edges should be regarded as non-existent. Therefore, it is better to store the graph with adjacency matrix.

The idea is Dijkstra algorithm. Note that the graph is a positive weight graph, so when Dijkstra calculates the shortest path, on the shortest path tree (of course, it is not necessarily a tree. It is possible that the shortest path of a point can be reached by two fathers, but multiple edges can still be added into a topological graph), the order of points out of the heap is actually a topological order, Therefore, the whole Dijkstra algorithm can calculate the shortest path of each point and update the number of shortest paths of the points it can reach at the same time by using the recursive idea of dynamic programming (if a shorter path is found, the number of paths will be assigned directly; if a shortest path of equal length is found, the number of paths will be accumulated). The code is as follows:

#include <iostream>
#include <cstring>
#include <queue>
using namespace std;

typedef pair<int, int> PII;

const int N = 2010, INF = 0x3f3f3f3f;
int n, m;
// Adjacency matrix graph
int g[N][N];
int dist[N], cnt[N];
bool st[N];

void dijkstra(int s) {
    memset(dist, 0x3f, sizeof dist);
    priority_queue<PII, vector<PII>, greater<PII> > heap;
    heap.push({0, s});

    dist[s] = 0;
    cnt[s] = 1;

    while (heap.size()) {
        auto t = heap.top();
        heap.pop();
        int v = t.second, d = t.first;

        if (st[v]) continue;
        st[v] = true;

        for (int i = 1; i <= n; i++) {
        	// Skip the points that cannot be reached and the points that have been calculated before
            if (g[v][i] == INF || st[i]) continue;

            if (dist[i] > d + g[v][i]) {
                dist[i] = d + g[v][i];
                cnt[i] = cnt[v];
                heap.push({dist[i], i});
            } else if (dist[i] == d + g[v][i]) {
                cnt[i] += cnt[v];
            }
        }
    }
}

int main() {
    cin >> n >> m;
    memset(g, 0x3f, sizeof g);
    while (m--) {
        int a, b, c;
        cin >> a >> b >> c;
        // If there are multiple edges, the shortest edge shall be taken
        g[a][b] = min(g[a][b], c);
    }

    dijkstra(1);

    if (dist[n] == INF) printf("No answer\n");
    else printf("%d %d\n", dist[n], cnt[n]);

    return 0;
}

Time complexity O ( E log ⁡ N ) O(E\log N) O(ElogN), space O ( N ) O(N) O(N).

Topics: Algorithm Dynamic Programming Graph Theory