(次短路) 已知一个有 个点 条边的有向图 ,并且给定图中的两个点 和 ,求次短路(长度严格大于最短路的最短路径)。如果不存在,输出一行 。如果存在,输出两行,第一行表示次短路的长度,第二行表示次短路的一个方案。
#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%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); }}① 处应填( )
② 处应填( )
③ 处应填( )
④ 处应填( )
⑤ 处应填( )