题意
题解
求单源最短路与次短路,并统计路径数。边权为正的图,用优先队列维护从源点拓展的路径,可以保证当前堆顶元素不会再被更新边权与路径数。可能的次短路存在两种情况:由最短路拓展;由次短路拓展。那么使用 D i j k s t r a Dijkstra Dijkstra 求解,堆中维护由最短路与次短路拓展的路径。总时间复杂度 O ( M log N ) O(M\log N) O(MlogN)。
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
typedef pair<int, int> P;
const int maxn = 1005, maxm = 10005;
int T, N, M, S, F, ds[maxn][2], cnt[maxn][2], pos[maxn];
int tot, head[maxn], to[maxm], nxt[maxm], cost[maxm];
inline void add(int x, int y, int z) { to[++tot] = y, cost[tot] = z, nxt[tot] = head[x], head[x] = tot; }
int Dijkstra(int s, int t)
{
memset(ds, 0x3f, sizeof(ds));
memset(cnt, 0, sizeof(cnt));
memset(pos, 0, sizeof(pos));
priority_queue<P, vector<P>, greater<P>> q;
ds[s][0] = 0, cnt[s][0] = 1;
q.push(P(0, s));
while (q.size())
{
int x = q.top().second;
q.pop();
if (pos[x] > 1)
{
if (x == t)
break;
continue;
}
for (int i = head[x]; i; i = nxt[i])
{
int y = to[i], z = ds[x][pos[x]] + cost[i], c = cnt[x][pos[x]];
if (z == ds[y][0])
cnt[y][0] += c;
else if (z < ds[y][0])
swap(z, ds[y][0]), swap(c, cnt[y][0]), q.push(P(ds[y][0], y));
if (z == ds[y][1])
cnt[y][1] += c;
else if (ds[y][0] < z && z < ds[y][1])
ds[y][1] = z, cnt[y][1] = c, q.push(P(ds[y][1], y));
}
++pos[x];
}
return cnt[t][0] + (ds[t][1] == ds[t][0] + 1 ? cnt[t][1] : 0);
}
int main()
{
scanf("%d", &T);
while (T--)
{
memset(head, 0, sizeof(head));
tot = 0;
scanf("%d%d", &N, &M);
for (int i = 1, x, y, z; i <= M; ++i)
scanf("%d%d%d", &x, &y, &z), add(x, y, z);
scanf("%d%d", &S, &F);
printf("%d\n", Dijkstra(S, F));
}
return 0;
}