(次短路) 已知一个有 n 个点 m 条边的有向图 G,并且给定图中的两个点 s 和 t,求次短路(长度严格大于最短路的最短路径)。如果不存在,输出一行 −1。如果存在,输出两行,第一行表示次短路的长度,第二行表示次短路的一个方案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | #include <cstdio> #include <queue> #include <utility> #include <cstring> using namespace std; const int maxn = 2e5+10, maxm = 1e6+10, inf = 522133279; int n, m, s, t; int head[maxn], nxt[maxm], to[maxm], w[maxm], tot = 1; int dis[maxn<<1], *dis2; int pre[maxn<<1], *pre2; bool vis[maxn<<1]; void add(int a, int b, int c) { ++tot; nxt[tot] = head[a]; to[tot] = b; w[tot] = c; head[a] = tot; } bool upd(int a, int b, int d, priority_queue<pair<int, int>> &q) { if (d >= dis[b]) return false; if (b < n) ___①___; q.push(___②___); dis[b] = d; pre[b] = a; return true; } void solve() { priority_queue<pair<int, int>> q; q.push(make_pair(0, s)); memset(dis, ___③___, sizeof(dis)); memset(pre, -1, sizeof(pre)); dis2 = dis+n; pre2 = pre+n; dis[s] = 0; while (!q.empty()) { int aa = q.top().second; q.pop(); if (vis[aa]) continue; vis[aa] = true; int a = aa % n; for (int e = head[a]; e; e = nxt[e]) { int b = to[e], c = w[e]; if (aa < n) { if (!upd(a, b, dis[a]+c, q)) ___④__; } else { upd(n+a, n+b, dis2[a]+c, q); } } } void out(int a) { if (a != s) { if (a < n) out(pre[a]); else out(___⑤___); } printf("%d%c", a%n+1, " \n"[a == n+t]); } int main() { scanf("%d%d%d", &n, &m, &s, &t); s--, t--; for (int i = 0; i < m; ++i) { int a, b, c; scanf("%d%d%d", &a, &b, &c); add(a-1, b-1, c); } solve(); if (dis2[t] == inf) puts("-1"); else { printf("%d\n", dis2[t]); out(n+t); } } |