@@ -16,7 +16,7 @@ namespace cp_algo::graph {
1616 : dist(n, inf), pre (n) {}
1717 };
1818
19- struct dijkstra_context : shortest_path_context {
19+ struct dijkstra_context : shortest_path_context {
2020 struct que_t {
2121 int64_t dist;
2222 node_index v;
@@ -44,23 +44,44 @@ namespace cp_algo::graph {
4444 }
4545 };
4646
47- struct spfa_context : shortest_path_context {
47+ struct spfa_context : shortest_path_context {
4848 std::queue<node_index> que;
4949 std::vector<char > flags;
5050 static constexpr char in_queue = 1 ;
5151 static constexpr char invalidated = 2 ;
52+
53+ spfa_context (int n) : shortest_path_context(n), flags(n) {}
54+
55+ void push (node_index, node_index v) {
56+ if (!(flags[v] & in_queue)) {
57+ que.push (v);
58+ flags[v] |= in_queue;
59+ }
60+ }
61+
62+ std::optional<node_index> next_node () {
63+ while (!que.empty ()) {
64+ node_index v = que.front ();
65+ que.pop ();
66+ flags[v] &= ~in_queue;
67+ if (!(flags[v] & invalidated)) {
68+ return v;
69+ }
70+ }
71+ return std::nullopt ;
72+ }
73+ };
74+
75+ struct deep_spfa_context : spfa_context {
5276 std::vector<std::basic_string<node_index>> dependents;
5377
54- spfa_context (int n) : shortest_path_context(n), flags (n), dependents(n) {}
78+ deep_spfa_context (int n) : spfa_context (n), dependents(n) {}
5579
5680 void push (node_index u, node_index v) {
5781 invalidate_subtree (v);
5882 dependents[u].push_back (v);
5983 flags[v] &= ~invalidated;
60- if (!(flags[v] & in_queue)) {
61- que.push (v);
62- flags[v] |= in_queue;
63- }
84+ spfa_context::push (u, v);
6485 }
6586
6687 void invalidate_subtree (node_index v) {
@@ -69,6 +90,7 @@ namespace cp_algo::graph {
6990 node_index u = to_invalidate.back ();
7091 to_invalidate.pop_back ();
7192 flags[u] |= invalidated;
93+ flags[u] &= ~in_queue;
7294 for (auto dep: dependents[u]) {
7395 if (pre [dep].u == u) {
7496 to_invalidate.push_back (dep);
@@ -77,18 +99,6 @@ namespace cp_algo::graph {
7799 dependents[u].clear ();
78100 }
79101 }
80-
81- std::optional<node_index> next_node () {
82- while (!que.empty ()) {
83- node_index v = que.front ();
84- que.pop ();
85- flags[v] &= ~in_queue;
86- if (!(flags[v] & invalidated)) {
87- return v;
88- }
89- }
90- return std::nullopt ;
91- }
92102 };
93103
94104 template <typename Context, weighted_graph_type graph>
@@ -119,14 +129,18 @@ namespace cp_algo::graph {
119129 shortest_path_context spfa (graph const & g, node_index s) {
120130 return sssp_impl<spfa_context>(g, s);
121131 }
132+ template <weighted_graph_type graph>
133+ shortest_path_context deep_spfa (graph const & g, node_index s) {
134+ return sssp_impl<deep_spfa_context>(g, s);
135+ }
122136
123137 template <weighted_graph_type graph>
124138 shortest_path_context single_source_shortest_path (graph const & g, node_index s) {
125139 bool negative_edges = false ;
126140 for (auto e: g.edges ()) {
127141 negative_edges |= e.w < 0 ;
128142 }
129- return negative_edges ? spfa (g, s) : dijkstra (g, s);
143+ return negative_edges ? deep_spfa (g, s) : dijkstra (g, s);
130144 }
131145
132146 std::vector<edge_index> recover_path (auto const & pre , node_index s, node_index t) {
0 commit comments