55#include < queue>
66namespace cp_algo ::graph {
77 struct shortest_path_context {
8- struct reverse {
9- node_index u;
10- edge_index e;
11- };
128 std::vector<int64_t > dist;
13- std::vector<reverse > pre ;
9+ std::vector<edge_index > pre ;
1410 static constexpr int64_t inf = 1e18 ;
1511 shortest_path_context (int n)
1612 : dist(n, inf), pre (n) {}
@@ -28,7 +24,7 @@ namespace cp_algo::graph {
2824
2925 dijkstra_context (int n) : shortest_path_context(n) {}
3026
31- void push (node_index, node_index v) {
27+ void push (node_index, edge_index, node_index v) {
3228 pq.push ({dist[v], v});
3329 }
3430
@@ -52,7 +48,7 @@ namespace cp_algo::graph {
5248
5349 spfa_context (int n) : shortest_path_context(n), flags(n) {}
5450
55- void push (node_index, node_index v) {
51+ void push (node_index, edge_index, node_index v) {
5652 if (!(flags[v] & in_queue)) {
5753 que.push (v);
5854 flags[v] |= in_queue;
@@ -73,15 +69,19 @@ namespace cp_algo::graph {
7369 };
7470
7571 struct deep_spfa_context : spfa_context {
76- std::vector<std::basic_string<node_index>> dependents;
72+ struct traverse_edge {
73+ edge_index e;
74+ node_index v;
75+ };
76+ std::vector<std::basic_string<traverse_edge>> dependents;
7777
7878 deep_spfa_context (int n) : spfa_context(n), dependents(n) {}
7979
80- void push (node_index u, node_index v) {
80+ void push (node_index u, edge_index e, node_index v) {
8181 invalidate_subtree (v);
82- dependents[u].push_back (v );
82+ dependents[u].push_back ({e, v} );
8383 flags[v] &= ~invalidated;
84- spfa_context::push (u, v);
84+ spfa_context::push (u, e, v);
8585 }
8686
8787 void invalidate_subtree (node_index v) {
@@ -91,9 +91,9 @@ namespace cp_algo::graph {
9191 to_invalidate.pop_back ();
9292 flags[u] |= invalidated;
9393 flags[u] &= ~in_queue;
94- for (auto dep : dependents[u]) {
95- if (pre [dep]. u == u ) {
96- to_invalidate.push_back (dep );
94+ for (auto [e, v] : dependents[u]) {
95+ if (pre [v] == e ) {
96+ to_invalidate.push_back (v );
9797 }
9898 }
9999 dependents[u].clear ();
@@ -105,16 +105,16 @@ namespace cp_algo::graph {
105105 Context sssp_impl (graph const & g, node_index s) {
106106 Context context (g.n ());
107107 context.dist [s] = 0 ;
108- context.push (s, s);
108+ context.push (s, - 1 , s);
109109 while (auto ov = context.next_node ()) {
110110 node_index v = *ov;
111111 for (auto e: g.outgoing (v)) {
112- node_index u = g.edge (e).to ;
112+ node_index u = g.edge (e).traverse (v) ;
113113 auto w = g.edge (e).w ;
114114 if (context.dist [v] + w < context.dist [u]) {
115115 context.dist [u] = context.dist [v] + w;
116- context.pre [u] = {v, e} ;
117- context.push (v, u);
116+ context.pre [u] = e ;
117+ context.push (v, e, u);
118118 }
119119 }
120120 }
@@ -143,12 +143,12 @@ namespace cp_algo::graph {
143143 return negative_edges ? deep_spfa (g, s) : dijkstra (g, s);
144144 }
145145
146- std::vector<edge_index> recover_path (auto const & pre , node_index s, node_index t) {
146+ std::vector<edge_index> recover_path (auto const & g, auto const & pre , node_index s, node_index t) {
147147 std::vector<edge_index> path;
148148 node_index v = t;
149149 while (v != s) {
150- path.push_back (pre [v]. e );
151- v = pre [v]. u ;
150+ path.push_back (pre [v]);
151+ v = g. edge ( pre [v]). traverse (v) ;
152152 }
153153 std::ranges::reverse (path);
154154 return path;
@@ -160,7 +160,7 @@ namespace cp_algo::graph {
160160 if (dist[t] == shortest_path_context::inf) {
161161 return std::nullopt ;
162162 }
163- return {{dist[t], recover_path (pre , s, t)}};
163+ return {{dist[t], recover_path (g, pre , s, t)}};
164164 }
165165}
166166#endif // CP_ALGO_GRAPH_SHORTEST_PATH_HPP
0 commit comments