AcWing 383. 观光
如果要求出最短路个数,那么就需要再拓扑图上做最短路,而能有拓扑结构的最短路模型一般只有Dijkstra和bfs两种算法。
而求次短路只需对每个点进行拆点,并且再求得最短路的同时维护一个次短路即可,每次先更新最短路,不能更新最短路再看能不能更新次短路。
代码:
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <queue> using namespace std; const int N = 1010, M = 100010; struct Node { int ver, dist, type; bool operator> (const Node &a) const { return dist > a.dist; } }; int h[N], ne[M], e[M], w[M]; int idx, n, m, S, F; int dist[N][2], f[N][2]; bool st[N][2]; void add(int a, int b, int c) { e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++ ; } int dijkstra() { memset(dist, 0x3f, sizeof dist); memset(f, 0, sizeof f); memset(st, 0, sizeof st); priority_queue<Node, vector<Node>, greater<Node>> heap; heap.push({S, 0, 0}); dist[S][0] = 0, f[S][0] = 1; while (heap.size()) { auto t = heap.top(); heap.pop(); int ver = t.ver, distance = t.dist, type = t.type, sum = f[ver][type]; if (st[ver][type]) continue; st[ver][type] = true; for (int i = h[ver]; i != -1; i = ne[i]) { int j = e[i]; if (dist[j][0] > distance + w[i]) { dist[j][1] = dist[j][0], f[j][1] = f[j][0]; // 如果最短路能被更新,那么当前的最短路就会变成次短路 heap.push({j, dist[j][1], 1}); // 次短路入队 dist[j][0] = distance + w[i], f[j][0] = sum; // 更新最短路 heap.push({j, dist[j][0], 0}); // 最短路入队 } else if (dist[j][0] == distance + w[i]) f[j][0] += sum; else if (dist[j][1] > distance + w[i]) // 先更新最短路,最短路不能更新再更新次短路 { dist[j][1] = distance + w[i], f[j][1] = sum; heap.push({j, dist[j][1], 1}); } else if (dist[j][1] == distance + w[i]) f[j][1] += sum; } } int res = f[F][0]; if (dist[F][0] + 1 == dist[F][1]) res += f[F][1]; return res; } int main() { int T; scanf("%d", &T); while (T -- ) { scanf("%d%d", &n, &m); memset(h, -1, sizeof h); idx = 0; while (m -- ) { int a, b, c; scanf("%d%d%d", &a, &b, &c); add(a, b, c); } scanf("%d%d", &S, &F); cout << dijkstra() << endl; } return 0; }