Aleph-w  1.9
General library for algorithms and data structures
Bellman_Ford.H
1 
2 /* Aleph-w
3 
4  / \ | | ___ _ __ | |__ __ __
5  / _ \ | |/ _ \ '_ \| '_ \ ____\ \ /\ / / Data structures & Algorithms
6  / ___ \| | __/ |_) | | | |_____\ V V / version 1.9b
7  /_/ \_\_|\___| .__/|_| |_| \_/\_/ https://github.com/lrleon/Aleph-w
8  |_|
9 
10  This file is part of Aleph-w library
11 
12  Copyright (c) 2002-2018 Leandro Rabindranath Leon & Alejandro Mujica
13 
14  This program is free software: you can redistribute it and/or modify
15  it under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  This program is distributed in the hope that it will be useful, but
20  WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  General Public License for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27 # ifndef BELLMAN_FORD_H
28 # define BELLMAN_FORD_H
29 
30 # include <tpl_dynListQueue.H>
31 # include <tpl_dynSetTree.H>
32 # include <tpl_graph_utils.H>
33 # include <Tarjan.H>
34 
35 namespace Aleph {
36 
37 template <class GT, class Distance> struct Bellman_Ford_Node_Info
38 {
39  int idx;
40  typename Distance::Distance_Type acum;
41 };
42 
48  template <class GT,
49  class Distance = Dft_Dist<GT>,
50  template <class, class> class Ait = Arc_Iterator,
51  template <class, class> class NAit = Out_Iterator,
52  class SA = Dft_Show_Arc<GT>>
54 {
55  typedef typename Distance::Distance_Type Distance_Type;
56 
57  using Node = typename GT::Node;
58  using Arc = typename GT::Arc;
59 
60  struct Sni
61  {
62  Distance_Type acum;
63  };
64 
65  struct Ni : public Sni
66  {
67  int idx; // índice en los arreglos de predecesores
68  };
69 
70  Distance_Type & acum(Node * p) noexcept
71  {
72  return ((Sni*) NODE_COOKIE(p))->acum;
73  }
74 
75  int & idx(Node * p) noexcept
76  {
77  return ((Ni*) NODE_COOKIE(p))->idx;
78  }
79 
81  const GT & g;
82  const Distance_Type Inf;
83  bool painted = false;
84  Node * s = nullptr;
85  SA sa;
86  Distance dist;
87 
88  // Inicializa sin usar los arreglos
89  void init_simple(Node * start)
90  {
91  typename GT::Node_Iterator it(g);
92  for (int i = 0; it.has_curr(); ++i, it.next_ne())
93  {
94  auto p = it.get_curr_ne();
95  g.reset_bit(p, Aleph::Spanning_Tree); // colocar bit en cero
96  auto ptr = new Sni;
97  ptr->acum = Inf;
98  NODE_BITS(p).set_bit(Spanning_Tree, false);
99  NODE_COOKIE(p) = ptr;
100  }
101  s = start;
102  acum(s) = 0;
103  g.reset_arcs();
104  }
105 
106  void init_with_indexes(Node * start)
107  {
108  arcs.reserve(g.get_num_nodes());
109  typename GT::Node_Iterator it(g);
110  for (int i = 0; it.has_curr(); ++i, it.next_ne())
111  {
112  arcs(i) = nullptr;
113  auto p = it.get_curr_ne();
114  g.reset_bit(p, Aleph::Spanning_Tree); // colocar bit en cero
115  auto ptr = new Ni;
116  ptr->acum = Inf;
117  ptr->idx = i;
118  NODE_BITS(p).set_bit(Spanning_Tree, false);
119  NODE_BITS(p).set_bit(Depth_First, false); // indicates if it is in queue
120  NODE_COOKIE(p) = ptr;
121  }
122 
123  s = start;
124  acum(s) = 0;
125 
126  g.reset_arcs();
127  }
128 
129  // libera la memoria asociada a los cookies
130  template <class Info_Type>
131  void uninit() noexcept
132  {
133  for (typename GT::Node_Iterator it(g); it.has_curr(); it.next_ne())
134  {
135  auto p = it.get_curr_ne();
136  delete (Info_Type*) NODE_COOKIE(p);
137  NODE_COOKIE(p) = nullptr;
138  }
139  }
140 
141  bool check_painted_arcs() noexcept
142  {
143  auto num_arcs = 0;
144  for (Ait<GT, SA> it(g, sa); it.has_curr(); it.next_ne())
145  if (IS_ARC_VISITED(it.get_curr_ne(), Aleph::Spanning_Tree))
146  ++num_arcs;
147 
148  return num_arcs == g.get_num_nodes() - 1 or num_arcs == g.get_num_nodes();
149  }
150 
151 public:
152 
153  Bellman_Ford(const GT & __g, Distance d = Distance(), SA __sa = SA())
154  : g(const_cast<GT&>(__g)), Inf(std::numeric_limits<Distance_Type>::max()),
155  painted(false), sa(__sa), dist(d)
156  {
157  // empty
158  }
159 
160 private:
161 
162  void relax_arcs() noexcept
163  {
164  const size_t & n = g.vsize();
165  for (int i = 0; i < n - 1; ++i)
166  for (Ait<GT, SA> it(g, sa); it.has_curr(); it.next_ne())
167  {
168  auto arc = it.get_curr_ne();
169  auto src = g.get_src_node(arc);
170  const auto & acum_src = acum(src);
171  if (acum_src == Inf)
172  continue;
173 
174  auto tgt = it.get_tgt_node_ne();
175  auto w = dist(arc);
176  auto sum = acum_src + w;
177  auto & acum_tgt = acum(tgt);
178  if (sum < acum_tgt) // relajar arco
179  {
180  const auto & index = idx(tgt);
181  arcs(index) = arc;
182  acum_tgt = sum;
183  }
184  }
185  }
186 
187  static void
188  put_in_queue(DynListQueue<typename GT::Node*> & q, typename GT::Node * p)
189  {
190  if (IS_NODE_VISITED(p, Depth_First)) // is already inside the queue?
191  return;
192  NODE_BITS(p).set_bit(Depth_First, true);
193  q.put(p);
194  }
195 
196  static typename GT::Node * get_from_queue(DynListQueue<typename GT::Node*>& q)
197  {
198  auto ret = q.get();
199  assert(IS_NODE_VISITED(ret, Depth_First));
200  NODE_BITS(ret).set_bit(Depth_First, false);
201  return ret;
202  }
203 
204  void relax_arcs(typename GT::Node * src, DynListQueue<typename GT::Node*> & q)
205  {
206  for (NAit<GT, SA> it(src, sa); it.has_curr(); it.next_ne())
207  {
208  auto arc = it.get_curr_ne();
209  auto src = g.get_src_node(arc);
210  const auto & acum_src = acum(src);
211  if (acum_src == Inf)
212  continue;
213 
214  auto tgt = g.get_tgt_node(arc);
215  auto w = dist(arc);
216  auto sum = acum_src + w;
217  auto & acum_tgt = acum(tgt);
218  if (sum < acum_tgt) // relajar arco
219  {
220  const auto & index = idx(tgt);
221  arcs(index) = arc;
222  acum_tgt = sum;
223  put_in_queue(q, tgt);
224  }
225  }
226  }
227 
228  void paint_tree() noexcept
229  { // pinta los nodos y arcos involucrados
230  const auto & n = g.vsize();
231  for (int i = 0; i < n; ++i)
232  {
233  auto arc = arcs(i);
234  if (arc == nullptr)
235  continue;
236 
237  ARC_BITS(arc).set_bit(Aleph::Spanning_Tree, true);
238  auto src = (Node*) arc->src_node;
239  auto tgt = (Node*) arc->tgt_node;
240  NODE_BITS(src).set_bit(Aleph::Spanning_Tree, true);
241  NODE_BITS(tgt).set_bit(Aleph::Spanning_Tree, true);
242  }
243  NODE_BITS(s).set_bit(Aleph::Spanning_Tree, true);
244 
245  assert(check_painted_arcs());
246 
247  painted = true;
248  }
249 
250  bool last_relax_and_prepare_check_negative_cycle() noexcept
251  {
252  bool negative_cycle = false;
253  for (Ait<GT, SA> it(g, sa); it.has_curr(); it.next_ne())
254  {
255  auto arc = it.get_curr_ne();
256  auto src = g.get_src_node(arc);
257  auto & acum_src = acum(src);
258  if (acum_src == Inf)
259  continue;
260 
261  auto tgt = g.get_tgt_node(arc);
262  auto d = dist(arc);
263  auto & acum_tgt = acum(tgt);
264  auto sum = acum_src + d;
265  if (sum < acum_tgt)
266  {
267  negative_cycle = true;
268  const auto & index = idx(tgt);
269  arcs(index) = arc;
270  acum_tgt = sum;
271  }
272  }
273  return negative_cycle;
274  }
275 
276  bool last_relax_and_test_negative_cycle() noexcept
277  {
278  for (Ait<GT, SA> it(g, sa); it.has_curr(); it.next_ne())
279  {
280  auto arc = it.get_curr_ne();
281  auto src = g.get_src_node(arc);
282  auto & acum_src = acum(src);
283  if (acum_src == Inf)
284  continue;
285 
286  auto tgt = g.get_tgt_node(arc);
287  auto d = dist(arc);
288  auto & acum_tgt = acum(tgt);
289  auto sum = acum_src + d;
290  if (sum < acum_tgt)
291  return true;
292  }
293  return false;
294  }
295 
296  void link_cookies_and_free(typename GT::Node * s) noexcept
297  {
298  uninit<Ni>();
299 
300  // construye los caminos invertidos hacia el nodo origen s
301  const auto & n = g.vsize();
302  for (int i = 0; i < n; ++i)
303  {
304  auto arc = arcs(i);
305  if (arc == nullptr)
306  continue;
307 
308  auto tgt = g.get_tgt_node(arc);
309  NODE_COOKIE(tgt) = g.get_src_node(arc);
310  }
311 
312  NODE_COOKIE(s) = nullptr; // por si acaso hay ciclo negativo
313 
314  arcs.cut_ne();
315  }
316 
317 public:
318 
328  bool paint_spanning_tree(Node * start)
329  {
330  init_with_indexes(start);
331 
332  relax_arcs();
333  bool negative_cycle = last_relax_and_prepare_check_negative_cycle();
334  paint_tree();
335  link_cookies_and_free(s);
336 
337  return negative_cycle;
338  }
339 
352  bool faster_paint_spanning_tree(Node * start)
353  {
354  init_with_indexes(start);
355 
356  const auto & n = g.get_num_nodes();
357 
359 
360  Node __sentinel;
361  Node * sentinel = &__sentinel;
362 
363  put_in_queue(q, s);
364  put_in_queue(q, sentinel);
365 
366  for (size_t i = 0; not q.is_empty(); )
367  {
368  auto src = get_from_queue(q);
369  if (src == sentinel) // ¿se saca el centinela?
370  {
371  if (i++ > n)
372  break;
373 
374  put_in_queue(q, sentinel);
375  }
376  else
377  relax_arcs(src, q);
378  }
379 
380  bool negative_cycle = last_relax_and_prepare_check_negative_cycle();
381  paint_tree();
382  link_cookies_and_free(s);
383 
384  return negative_cycle;
385  }
386 
387 private:
388 
389  Node * create_dummy_node()
390  {
391  s = const_cast<GT&>(g).insert_node(typename GT::Node_Type());
392  for (typename GT::Node_Iterator it(g); it.has_curr(); it.next_ne())
393  {
394  auto p = it.get_curr_ne();
395  if (p == s)
396  continue;
397  auto a = const_cast<GT&>(g).insert_arc(s, p);
398  Distance::set_zero(a);
399  }
400  return s;
401  }
402 
403  template <class Info_Type>
404  void remove_dummy_node(Node * p)
405  {
406  delete (Info_Type*) NODE_COOKIE(p);
407  const_cast<GT&>(g).remove_node(p);
408  }
409 
410 public:
411 
415  bool has_negative_cycle(Node * start)
416  {
417  init_with_indexes(start);
418  s = start;
419  acum(s) = 0;
420 
421  relax_arcs();
422  bool negative_cycle = last_relax_and_test_negative_cycle();
423  uninit<Ni>();
424 
425  return negative_cycle;
426  }
427 
428  bool has_negative_cycle()
429  {
430  create_dummy_node();
431  auto ret = has_negative_cycle(s);
432  remove_dummy_node<Ni>(s);
433 
434  return ret;
435  }
436 
437 private:
438 
439  Path<GT> search_negative_cycle_on_partial_graph()
440  {
441  GT aux = build_spanning_tree<GT>(arcs);
442 
443  // we map because Tarjan algorithm modifies cookies
445  for (typename GT::Node_Iterator it(aux); it.has_curr(); it.next_ne())
446  {
447  auto p = it.get_curr_ne();
448  table.insert(p, (Node*) NODE_COOKIE(p));
449  }
450 
451  Path<GT> path(aux);
452  if (Tarjan_Connected_Components<GT, NAit, SA>(sa).compute_cycle(aux, path))
453  {
454  Path<GT> ret(g);
455  for (typename Path<GT>::Iterator it(path); it.has_current_node();
456  it.next_ne())
457  ret.append_directed((Node*) table.find(it.get_current_node_ne()));
458  return ret;
459  }
460 
461  return Path<GT>(g);
462  }
463 
464 public:
465 
478  {
479  init_with_indexes(start);
480 
481  relax_arcs();
482  bool negative_cycle = last_relax_and_prepare_check_negative_cycle();
483  if (not negative_cycle)
484  {
485  link_cookies_and_free(s);
486  return Path<GT>(g);
487  }
488 
489  Path<GT> ret = search_negative_cycle_on_partial_graph();
490  if (ret.is_empty())
491  WARNING("Serious inconsistency. Bellman-Ford algorithm has detected\n"
492  "a negative cycle, but Tarjan algorithm executed on partial\n"
493  "graph has not found such cycle\n\n"
494  "Be very careful, this is provably a bug");
495 
496  link_cookies_and_free(s);
497  return ret;
498  }
499 
506  {
507  auto start = create_dummy_node();
508  auto ret_val = test_negative_cycle(start);
509  remove_dummy_node<Ni>(start);
510  return ret_val;
511  }
512 
556  tuple<Path<GT>, size_t>
557  search_negative_cycle(Node * start, double it_factor, const size_t step)
558  {
559  init_with_indexes(start);
560 
561  const auto & n = g.get_num_nodes();
563  Node __sentinel;
564  Node * sentinel = &__sentinel;
565  put_in_queue(q, s);
566  put_in_queue(q, sentinel);
567 
568  double threshold = it_factor*n;
569  Path<GT> ret(g);
570 
571  size_t i = 0;
572  while (not q.is_empty())
573  {
574  auto src = get_from_queue(q);
575  if (src == sentinel)
576  {
577  if (i++ > n)
578  break;
579 
580  put_in_queue(q, sentinel);
581  if (i >= threshold) // must I search negative cycles?
582  {
583  ret = search_negative_cycle_on_partial_graph();
584  if (not ret.is_empty()) // negative cycle found?
585  {
586  link_cookies_and_free(s);
587  return make_tuple(std::forward<Path<GT>>(ret), i);
588  }
589  threshold += step;
590  }
591  }
592  else
593  relax_arcs(src, q);
594  }
595 
596  bool negative_cycle = last_relax_and_prepare_check_negative_cycle();
597  if (negative_cycle)
598  {
599  ret = search_negative_cycle_on_partial_graph();
600  if (ret.is_empty())
601  WARNING("Serious inconsistency. Bellman-Ford algorithm has detected\n"
602  "a negative cycle, but Tarjan algorithm executed on partial\n"
603  "graph has not found such cycle\n\n"
604  "Be very careful, this provably is a bug");
605  }
606 
607  link_cookies_and_free(s);
608  return make_tuple(std::forward<Path<GT>>(ret), i);
609  }
610 
626  {
627  init_with_indexes(start);
628 
629  const auto & n = g.get_num_nodes();
631  Node __sentinel;
632  Node * sentinel = &__sentinel;
633  put_in_queue(q, s);
634  put_in_queue(q, sentinel);
635 
636  Path<GT> ret(g);
637  for (size_t i = 0; not q.is_empty(); /* nothing */)
638  {
639  auto src = get_from_queue(q);
640  if (src == sentinel)
641  {
642  if (i++ > n)
643  break;
644 
645  put_in_queue(q, sentinel);
646  }
647  else
648  relax_arcs(src, q);
649  }
650 
651  bool negative_cycle = last_relax_and_prepare_check_negative_cycle();
652  if (negative_cycle)
653  {
654  ret = search_negative_cycle_on_partial_graph();
655  if (ret.is_empty())
656  WARNING("Serious inconsistency. Bellman-Ford algorithm has detected\n"
657  "a negative cycle, but Tarjan algorithm executed on partial\n"
658  "graph has not found such cycle\n\n"
659  "Be very careful, this provably is a bug");
660  }
661 
662  link_cookies_and_free(s);
663 
664  return ret;
665  }
666 
677  tuple<Path<GT>, size_t> search_negative_cycle(double it_factor,
678  const size_t step)
679  {
680  auto start = create_dummy_node();
681  auto ret_val = search_negative_cycle(start, it_factor, step);
682  remove_dummy_node<Ni>(start);
683  return ret_val;
684  }
685 
689  Path<GT> search_negative_cycle()
690  {
691  auto start = create_dummy_node();
692  auto ret_val = search_negative_cycle(start);
693  remove_dummy_node<Ni>(start);
694  return ret_val;
695  }
696 
697 
709  {
710  return arcs;
711  }
712 
724  void build_tree(GT & tree, bool with_map = true)
725  {
726  if (not painted and with_map)
727  throw std::domain_error("Spanning tree has not been painted");
728 
729  clear_graph(tree);
730 
732  for (typename GT::Node_Iterator it(g); it.has_curr(); it.next_ne())
733  {
734  auto gp = it.get_curr_ne();
735  auto tp = tree.insert_node(gp->get_info());
736  table.insert(gp, tp);
737  }
738 
739  for (typename GT::Node_Iterator it(g); it.has_curr(); it.next_ne())
740  {
741  auto gtgt = it.get_curr_ne();
742  auto gsrc = (Node*) NODE_COOKIE(gtgt);
743  if (gsrc == nullptr)
744  continue; // Se trata del nodo origen del árbol abarcador
745 
746  auto garc_ptr = g.arcs(gsrc).find_ptr([gsrc, gtgt] (Arc * a)
747  {
748  return a->src_node == gsrc and a->tgt_node == gtgt;
749  });
750  assert(garc_ptr and IS_ARC_VISITED(*garc_ptr, Aleph::Spanning_Tree));
751  auto garc = *garc_ptr;
752  assert(garc->src_node == gsrc and garc->tgt_node == gtgt);
753  auto tsrc_ptr = table.search(gsrc);
754  auto ttgt_ptr = table.search(gtgt);
755  assert(tsrc_ptr and ttgt_ptr);
756  auto tarc = tree.insert_arc(tsrc_ptr->second, ttgt_ptr->second,
757  garc->get_info());
758  if (with_map)
759  GT::map_arcs(garc, tarc);
760  }
761 
762  if (with_map)
763  table.for_each([] (const auto & p) { GT::map_nodes(p.first, p.second); });
764  }
765 
766  bool test_negative_cycle(typename GT::Node * s, Path<GT> & cycle)
767  {
768  cycle = test_negative_cycle(s);
769  return not cycle.is_empty();
770  }
771 
772  bool test_negative_cycle(Path<GT> & cycle)
773  {
774  cycle = test_negative_cycle();
775  return not cycle.is_empty();
776  }
777 
778  Distance_Type get_min_path(typename GT::Node * end, Path<GT> & path)
779  {
780  if (not painted)
781  throw std::domain_error("Graph has not previously painted");
782 
783  return Aleph::get_min_path<GT, Distance>(s, end, path);
784  }
785 
799  {
800  create_dummy_node();
801 
802  init_with_indexes(s);
803 
804  const auto & n = g.get_num_nodes();
805 
807 
808  Node __sentinel;
809  Node * sentinel = &__sentinel;
810 
811  put_in_queue(q, s);
812  put_in_queue(q, sentinel);
813 
814  bool negative_cycle = false;
815  for (int i = 0; not q.is_empty() and not negative_cycle; /* nada */)
816  {
817  auto src = get_from_queue(q);
818  if (src == sentinel) // ¿se saca el centinela?
819  {
820  if (i++ > n)
821  break;
822  else
823  put_in_queue(q, sentinel);
824  }
825  else
826  relax_arcs(src, q);
827  }
828 
829  negative_cycle = last_relax_and_prepare_check_negative_cycle();
830  remove_dummy_node<Ni>(s);
831 
833 
834  // build mapping if there are no negative cycles
835  if (not negative_cycle)
836  for (auto it = g.get_node_it(); it.has_curr(); it.next_ne())
837  {
838  auto p = it.get_curr_ne();
839  ret.insert(p, acum(p));
840  }
841 
842  uninit<Ni>();
843  arcs.cut();
844 
845  if (negative_cycle)
846  throw domain_error("negative cycles detected");
847 
848  return ret;
849  }
850 };
851 
872  template <class GT,
873  class Distance = Dft_Dist<GT>,
874  template <class, class> class Ait = Arc_Iterator,
875  template <class, class> class NAit = Node_Arc_Iterator,
876  class SA = Dft_Show_Arc<GT>>
878 {
888  bool operator () (const GT & g, Path<GT> & path,
889  Distance & d, SA & sa) const
890  {
892  test_negative_cycle(path);
893  }
894 
895  bool operator () (const GT & g, Path<GT> & path,
896  Distance && d = Distance(), SA && sa = SA()) const
897  {
899  test_negative_cycle(path);
900  }
901 
912  bool operator () (const GT & g, typename GT::Node * s,
913  Path<GT> & path, Distance & d, SA & sa) const
914  {
916  test_negative_cycle(s, path);
917  }
918 
919  bool operator () (const GT & g, typename GT::Node * s,
920  Path<GT> & path, Distance && d = Distance(),
921  SA && sa = SA()) const
922  {
924  test_negative_cycle(s, path);
925  }
926 
927  Path<GT> operator () (const GT & g, typename GT::Node * s,
928  Distance & d, SA & sa, double it_factor = 0.7) const
929  {
931  search_negative_cycle(s, it_factor);
932  }
933 
934  Path<GT> operator () (const GT & g, typename GT::Node * s,
935  Distance && d = Distance(), SA && sa = SA(),
936  double it_factor = 0.7) const
937  {
939  search_negative_cycle(s, it_factor);
940  }
941 
942  Path<GT> operator () (const GT & g, Distance & d, SA & sa,
943  double it_factor = 0.7) const
944  {
946  search_negative_cycle(it_factor);
947  }
948 
949  Path<GT>
950  operator () (const GT & g, Distance && d = Distance(), SA && sa = SA(),
951  double it_factor = 0.7) const
952  {
954  search_negative_cycle(it_factor);
955  }
956 };
957 
958 
959 # undef NI
960 # undef IDX
961 # undef ACU
962 } // end namespace Aleph
963 
964 # endif // BELLMAN_FORD_H
Path< GT > test_negative_cycle()
Definition: Bellman_Ford.H:505
void reserve(const size_t l, const size_t r)
Definition: tpl_dynArray.H:998
void clear_graph(GT &g) noexcept
Definition: tpl_graph.H:3463
Definition: tpl_graph.H:1225
Definition: Bellman_Ford.H:877
Pair * insert(const Key &key, const Data &data)
Definition: tpl_dynMapTree.H:112
void cut(const size_t new_dim=0)
Definition: tpl_dynArray.H:1104
bool has_current_node() const noexcept
Return true if the iterator has a current node.
Definition: tpl_graph.H:3243
#define NODE_COOKIE(p)
Definition: aleph-graph.H:333
bool is_empty() const noexcept
rioReturn true if this is empty
Definition: tpl_dynListQueue.H:112
bool faster_paint_spanning_tree(Node *start)
Definition: Bellman_Ford.H:352
Definition: tpl_dynMapTree.H:62
#define IS_NODE_VISITED(p, bit)
Definition: aleph-graph.H:327
Definition: tpl_dynListQueue.H:50
void map_arcs(typename GTS::Arc *p, typename GTT::Arc *q) noexcept
Definition: tpl_graph.H:3445
#define IS_ARC_VISITED(p, bit)
Definition: aleph-graph.H:360
tuple< Path< GT >, size_t > search_negative_cycle(Node *start, double it_factor, const size_t step)
Definition: Bellman_Ford.H:557
Definition: tpl_graph.H:53
DynList< typename GT::Arc * > arcs(typename GT::Node *p, SA sa=SA())
Definition: tpl_graph.H:1893
void map_nodes(typename GTS::Node *p, typename GTT::Node *q) noexcept
Definition: tpl_graph.H:3419
Definition: ah-comb.H:35
Definition: Bellman_Ford.H:53
Definition: tpl_graph.H:1063
Path< GT > search_negative_cycle(Node *start)
Definition: Bellman_Ford.H:625
void append_directed(Node *p)
Definition: tpl_graph.H:2880
DynMapTree< Node *, Distance_Type > compute_nodes_weights()
Definition: Bellman_Ford.H:798
Pair * search(const Key &key) const noexcept
Definition: tpl_dynMapTree.H:214
Definition: tpl_graph.H:1796
#define NODE_BITS(p)
Definition: aleph-graph.H:305
bool has_negative_cycle(Node *start)
Definition: Bellman_Ford.H:415
DynArray< Arc * > extract_mim_spanning_tree()
Definition: Bellman_Ford.H:708
Definition: tpl_graph_utils.H:1753
bool paint_spanning_tree(Node *start)
Definition: Bellman_Ford.H:328
void build_tree(GT &tree, bool with_map=true)
Definition: Bellman_Ford.H:724
bool is_empty() const noexcept
Return true if the path is empty.
Definition: tpl_graph.H:2758
#define ARC_BITS(p)
Definition: aleph-graph.H:351
Definition: tpl_dynArray.H:159
T get()
Definition: tpl_dynListQueue.H:165
Definition: tpl_graph.H:1177
Path< GT > test_negative_cycle(Node *start)
Definition: Bellman_Ford.H:477
Definition: tpl_graph.H:3135
T & put(const T &data)
The type of element.
Definition: tpl_dynListQueue.H:125
Definition: Tarjan.H:52

Leandro Rabindranath León