Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

MaxFlowGoldbergTarjan.h
Go to the documentation of this file.
1 
33 #pragma once
34 
35 #include <ogdf/basic/Array.h>
36 #include <ogdf/basic/Graph.h>
37 #include <ogdf/basic/GraphList.h>
38 #include <ogdf/basic/List.h>
39 #include <ogdf/basic/basic.h>
41 
42 #include <algorithm>
43 
44 //#define OGDF_GT_USE_GAP_RELABEL_HEURISTIC
45 #define OGDF_GT_USE_MAX_ACTIVE_LABEL
46 //#ifdef OGDF_GT_USE_GAP_RELABEL_HEURISTIC
47 //#define OGDF_GT_GRH_STEPS 1 // gap relabel frequency: call gapRelabel() after OGDF_GT_GRH_STEPS relabel() operations (1 == off)
48 //#endif
49 #define OGDF_GT_USE_PUSH_RELABEL_SECOND_STAGE
50 
51 // world666 is much better without OGDF_GT_USE_PUSH_RELABEL_SECOND_STAGE
52 
53 namespace ogdf {
54 
56 
59 template<typename TCap>
60 class MaxFlowGoldbergTarjan : public MaxFlowModule<TCap> {
62  NodeArray<TCap> m_ex; // ex_f(v) values will be saved here to save runtime
63 #ifdef OGDF_GT_USE_MAX_ACTIVE_LABEL
64  NodeArray<ListIterator<node>> m_activeLabelListPosition; // holds the iterator of every active node in the corresp. list of m_labeList
65  Array<List<node>> m_activeLabelList; // array indexed by label, contains list of active nodes with that label
66  int m_maxLabel = 0; // the maximum label among all active nodes
67 #endif
68 #ifdef OGDF_GT_USE_GAP_RELABEL_HEURISTIC
69  NodeArray<ListIterator<node>> m_labelListPosition; // holds the iterator of every node in the corresp. list of m_labeList
70  Array<List<node>> m_labelList; // array indexed by label, contains list of nodes with that label
71 #endif
72 
75 
76  inline TCap getCap(const edge e) const {
77  return e->target() == *this->m_s ? 0 : (*this->m_cap)[e];
78  }
79 
80  inline bool isResidualEdge(const adjEntry adj) const {
81  const edge e = adj->theEdge();
82  if (adj->theNode() == e->source()) {
83  return this->m_et->less((*this->m_flow)[e], getCap(e));
84  }
85  return this->m_et->greater((*this->m_flow)[e], (TCap)0);
86  }
87 
88  inline bool isAdmissible(const adjEntry adj) const {
89  OGDF_ASSERT(adj);
90  return isResidualEdge(adj) && m_label[adj->theNode()] == m_label[adj->twinNode()] + 1;
91  }
92 
93  inline bool isActive(const node v) const {
94  OGDF_ASSERT((v != *this->m_s && v != *this->m_t)
95  || (m_label[*this->m_s] == this->m_G->numberOfNodes() && m_label[*this->m_t] == 0));
96  return this->m_et->greater(m_ex[v], (TCap)0) && this->m_G->numberOfNodes() > m_label[v]
97  && m_label[v] > 0;
98  }
99 
100 #ifdef OGDF_GT_USE_MAX_ACTIVE_LABEL
101  inline void setActive(const node v) {
102  const int label = m_label[v];
103  OGDF_ASSERT(0 < label);
104  OGDF_ASSERT(label < this->m_G->numberOfNodes());
106  m_activeLabelListPosition[v] = m_activeLabelList[label].pushBack(v);
107  if (label > m_maxLabel) {
108  m_maxLabel = label;
109  }
110  }
111 
112  inline void findNewMaxLabel() {
113  while (m_maxLabel > 0 && m_activeLabelList[m_maxLabel].empty()) {
114  --m_maxLabel;
115  }
116  }
117 
118  inline void setInactive(const node v) {
121  m_activeLabelListPosition[v] = nullptr;
122  findNewMaxLabel();
123  }
124 #endif
125 
126  // sets label of v, maintaining m_labelList (moves node v to the correct list in the array)
127  inline void setLabel(const node v, int label) {
128 #ifdef OGDF_GT_USE_GAP_RELABEL_HEURISTIC
129  if (m_labelListPosition[v].valid()) {
130  m_labelList[m_label[v]].del(
131  m_labelListPosition[v]); // delete node from old list using noted position
132  }
133  m_labelListPosition[v] =
134  m_labelList[label].pushBack(v); // push node to new list and update iterator
135 #endif
136 #ifdef OGDF_GT_USE_MAX_ACTIVE_LABEL
137  if (m_activeLabelListPosition[v].valid()) {
138  OGDF_ASSERT(0 < m_label[v]);
139  OGDF_ASSERT(m_label[v] < this->m_G->numberOfNodes());
140  setInactive(v);
141  }
142  m_label[v] = label; // update label
143  if (v != *this->m_s && v != *this->m_t && isActive(v)) {
144  setActive(v);
145  }
146 #else
147  m_label[v] = label; // update label
148 #endif
149  }
150 
151 #ifdef OGDF_GT_USE_GAP_RELABEL_HEURISTIC
152  void gapRelabel() {
153 # ifdef OGDF_GT_USE_MAX_ACTIVE_LABEL
154  // XXX: this is a test but it seems to work and it seems to be fast!
155  const int n = m_maxLabel + 1;
156 # else
157  const int n = this->m_G->numberOfNodes();
158 # endif
159  for (int i = 1; i < n - 1; ++i) {
160  if (m_labelList[i].empty()) {
161  for (int j = i + 1; j < n; ++j) {
162  while (!m_labelList[j].empty()) {
163  setLabel(m_labelList[j].front(), this->m_G->numberOfNodes());
164  }
165  }
166  break;
167  }
168  }
169  }
170 #endif
171 
172  void push(const adjEntry adj) {
173  const edge e = adj->theEdge();
174  const node v = adj->theNode();
175  if (v == e->source()) {
176  const TCap value = min(m_ex[v], getCap(e) - (*this->m_flow)[e]);
177  OGDF_ASSERT(this->m_et->geq(value, (TCap)0));
178  (*this->m_flow)[e] += value;
179  m_ex[v] -= value;
180  m_ex[adj->twinNode()] += value;
181  } else {
182  const TCap value = min(m_ex[v], (*this->m_flow)[adj]);
183  OGDF_ASSERT(this->m_et->geq(value, (TCap)0));
184  (*this->m_flow)[adj] -= value;
185  m_ex[v] -= value;
186  m_ex[adj->twinNode()] += value;
187  }
188  }
189 
190  void globalRelabel() {
191  // breadth-first search to relabel nodes with their respective distance to the sink in the residual graph
192  const int n = this->m_G->numberOfNodes();
193  NodeArray<int> dist(*this->m_G, n); // distance array
194  List<node> queue; // reachable, not processed nodes
195  dist[*this->m_t] = 0;
196  queue.pushBack(*this->m_t);
197  while (!queue.empty()) { // is there a node to check?
198  node w = queue.popFrontRet();
199  for (adjEntry adj : w->adjEntries) {
200  node x = adj->twinNode();
201  if (isResidualEdge(adj->twin()) && dist[x] == n) { // not already seen
202  dist[x] = dist[w] + 1; // set distance of node to sink
203  queue.pushBack(x);
204  }
205  }
206  }
207  // set distance of unreachable nodes to "number of nodes" thus making them inactive
208  for (node w : this->m_G->nodes) {
209  setLabel(w, dist[w]);
210  }
211  }
212 
213  void relabel(const node v) {
214  int minLabel = this->m_G->numberOfNodes() - 1;
215  for (adjEntry adj : v->adjEntries) {
216  if (isResidualEdge(adj)) {
217  const int label = m_label[adj->twinNode()];
218  if (label < minLabel) {
219  minLabel = label;
220  }
221  }
222  }
223  if (minLabel + 1 != m_label[v]) { // == can happen after global relabel
224  setLabel(v, minLabel + 1);
225  }
226  }
227 
228  void relabelStage2(const node v) {
229  int minLabel = this->m_G->numberOfNodes() - 1;
230  for (adjEntry adj : v->adjEntries) {
231  if (isResidualEdge(adj)) {
232  const int label = m_label[adj->twinNode()];
233  if (label < minLabel) {
234  minLabel = label;
235  }
236  }
237  }
238  OGDF_ASSERT(minLabel + 1 != m_label[v]);
239  m_label[v] = minLabel + 1;
240  }
241 
242 public:
243  // first stage: push excess towards sink
244  TCap computeValue(const EdgeArray<TCap>& cap, const node& s, const node& t) {
245  // TODO: init this stuff in the module?
246  this->m_s = &s;
247  this->m_t = &t;
248  this->m_cap = &cap;
249  this->m_flow->init(*this->m_G, (TCap)0);
251 
252  m_label.init(*this->m_G);
253  m_ex.init(*this->m_G, 0);
254 #ifdef OGDF_GT_USE_MAX_ACTIVE_LABEL
255  m_activeLabelListPosition.init(*this->m_G, nullptr);
256  m_activeLabelList.init(1, this->m_G->numberOfNodes() - 1);
257  m_maxLabel = 0;
258 #endif
259 #ifdef OGDF_GT_USE_GAP_RELABEL_HEURISTIC
260  m_labelListPosition.init(*this->m_G, nullptr);
261  m_labelList.init(this->m_G->numberOfNodes() + 1);
262 #endif
263  m_cutNodes.clear();
264 
265  // initialize residual graph for first preflow
266  for (edge e : this->m_G->edges) {
267  if (e->source() == *this->m_s && e->target() != *this->m_s) { // ignore loops
268  (*this->m_flow)[e] = getCap(e);
269  m_ex[e->target()] += getCap(e); // "+" needed for the case of multigraphs
270  }
271  }
272 
273  if (*this->m_t == *this->m_s) {
274  return (TCap)0;
275  }
276 
277  NodeArray<adjEntry> curr(*this->m_G);
278  for (node v = this->m_G->firstNode(); v; v = v->succ()) {
279  curr[v] = v->firstAdj();
280  }
281 
282  globalRelabel(); // initialize distance labels
283 
284  int relCount = 0; // counts the relabel operations for the global relabeling heuristic
285 #ifdef OGDF_GT_USE_MAX_ACTIVE_LABEL
286  while (m_maxLabel != 0) {
288  const node v = m_activeLabelList[m_maxLabel].front();
291 #else
292  List<node> active;
293  for (adjEntry adj : (*this->m_s)->adjEntries) {
294  node w = adj->theEdge()->target();
295  if (w != *this->m_s) {
296  active.pushBack(w);
297  }
298  }
299  while (!active.empty()) {
300  const node v = active.front();
301 #endif
302  adjEntry& adj = curr[v];
303  if (v == *this->m_s || v == *this->m_t || !isActive(v)) {
304  // source, sink or not active: remove activity status
305 #ifdef OGDF_GT_USE_MAX_ACTIVE_LABEL
306  setInactive(v);
307 #else
308  active.popFront();
309 #endif
310  } else {
311  while (this->m_et->greater(m_ex[v], (TCap)0)) {
312  if (isAdmissible(adj)) {
313  // push and adjacent node becomes active
314 #ifdef OGDF_GT_USE_MAX_ACTIVE_LABEL
315  const node w = adj->twinNode();
316  if (w != *this->m_s && w != *this->m_t && !isActive(w)) {
317  // w will become active after push
318  setActive(w);
319  }
320  push(adj);
321  if (v != *this->m_s && !isActive(v)) {
322  setInactive(v);
323  }
324 #else
325  push(adj);
326  active.pushBack(adj->twinNode());
327 #endif
328  } else {
329  if (adj != v->lastAdj()) {
330  adj = adj->succ();
331  } else { // end of adjacency list
332  adj = v->firstAdj();
333  relabel(v);
334  ++relCount;
335 #ifdef OGDF_GT_USE_GAP_RELABEL_HEURISTIC
336  // only gapRelabel if we do not do a globalRelabel directly afterwards
337  if (relCount != this->m_G->numberOfNodes()
338 # if (OGDF_GT_GRH_STEPS > 1)
339  && relCount % OGDF_GT_GRH_STEPS
340  == 0 // obey frequency of gap relabel heuristic
341 # endif
342  ) {
343  gapRelabel();
344  }
345 #endif
346  break;
347  }
348  }
349  }
350  if (relCount == this->m_G->numberOfNodes()) {
351  relCount = 0;
352  globalRelabel();
353  }
354  }
355  }
356 
357  TCap result = 0;
358  for (adjEntry adj : (*this->m_t)->adjEntries) {
359  edge e = adj->theEdge();
360  if (e->target() == *this->m_t) {
361  result += (*this->m_flow)[e];
362  } else {
363  result -= (*this->m_flow)[e];
364  }
365  }
366  return result;
367  }
368 
369  // second stage: push excess that has not reached the sink back towards source
371  List<node> active;
372 #ifdef OGDF_GT_USE_PUSH_RELABEL_SECOND_STAGE
373  NodeArray<adjEntry> curr(*this->m_G);
374  for (node v = this->m_G->firstNode(); v; v = v->succ()) {
375  curr[v] = v->firstAdj();
376  m_label[v] = 1;
377  if (this->m_et->greater(m_ex[v], (TCap)0) && v != *this->m_s && v != *this->m_t) {
378  active.pushBack(v);
379  }
380  }
381  if (active.empty()) {
382  return;
383  }
384 
385  m_label[*this->m_s] = 0;
386  while (!active.empty()) {
387  node v = active.front();
388  if (v == *this->m_s || v == *this->m_t || !isActive(v)) {
389  active.popFront();
390  } else {
391  adjEntry& adj = curr[v];
392  if (isAdmissible(adj)) {
393  push(adj);
394  active.pushBack(adj->twinNode());
395  } else {
396  if (adj == v->lastAdj()) {
397  // no admissible outgoing edge found -> relabel node!
398  relabelStage2(v);
399  adj = v->firstAdj();
400 # if 0
401  // node is still active but move it to the end of the queue
402  // (don't know if this is really necessary)
403  active.popFront();
404  active.pushBack(v);
405 # endif
406  } else {
407  adj = adj->succ();
408  }
409  }
410  }
411  }
412 #else // USE_PUSH_RELABEL_SECOND_STAGE
413  m_ex[*this->m_s] = m_ex[*this->m_t] = 0;
414  for (node v = this->m_G->firstNode(); v; v = v->succ()) {
415  if (this->m_et->greater(m_ex[v], (TCap)0)) {
416  active.pushBack(v);
417  }
418  }
419  while (!active.empty()) {
420  const node v = active.popFrontRet();
421  if (this->m_et->greater(m_ex[v], (TCap)0) && v != *this->m_s && v != *this->m_t) {
422  for (adjEntry adj = v->firstAdj(); adj; adj = adj->succ()) {
423  const edge e = adj->theEdge();
424  const node u = e->source();
425  if (u != v) { // e is incoming edge
426  if (this->m_et->greater(m_ex[v], (TCap)0) && isResidualEdge(adj)) {
427  push(adj);
428  if (u != *this->m_s) {
429  active.pushFront(u);
430  }
431  }
432  }
433  }
434  }
435  }
436 #endif // USE_PUSH_RELABEL_SECOND_STAGE
437  }
438 
444 };
445 
446 }
ogdf
The namespace for all OGDF objects.
Definition: multilevelmixer.cpp:39
ogdf::MaxFlowGoldbergTarjan::relabel
void relabel(const node v)
Definition: MaxFlowGoldbergTarjan.h:213
Graph.h
Includes declaration of graph class.
ogdf::MaxFlowModule< TCap >::isFeasibleInstance
bool isFeasibleInstance() const
Return whether the instance is feasible, i.e. the capacities are non-negative.
Definition: MaxFlowModule.h:148
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:66
MaxFlowModule.h
Interface for Max Flow Algorithms.
ogdf::AdjElement::theNode
node theNode() const
Returns the node whose adjacency list contains this element.
Definition: Graph_d.h:166
ogdf::List::popFront
void popFront()
Removes the first element from the list.
Definition: List.h:1585
ogdf::MaxFlowModule< TCap >::m_t
const node * m_t
Pointer to the sink node.
Definition: MaxFlowModule.h:48
ogdf::MaxFlowGoldbergTarjan::m_cutEdges
List< edge > m_cutEdges
Definition: MaxFlowGoldbergTarjan.h:74
ogdf::begin
HypergraphRegistry< HypernodeElement >::iterator begin(const HypergraphRegistry< HypernodeElement > &self)
ogdf::NodeElement::lastAdj
adjEntry lastAdj() const
Returns the last entry in the adjacency list.
Definition: Graph_d.h:289
ogdf::MaxFlowGoldbergTarjan::m_label
NodeArray< int > m_label
Definition: MaxFlowGoldbergTarjan.h:61
ogdf::MaxFlowGoldbergTarjan::getCap
TCap getCap(const edge e) const
Definition: MaxFlowGoldbergTarjan.h:76
ogdf::List::popFrontRet
E popFrontRet()
Removes the first element from the list and returns it.
Definition: List.h:1591
ogdf::MaxFlowGoldbergTarjan::isActive
bool isActive(const node v) const
Definition: MaxFlowGoldbergTarjan.h:93
ogdf::MaxFlowGoldbergTarjan
Computes a max flow via Preflow-Push (global relabeling and gap relabeling heuristic).
Definition: MaxFlowGoldbergTarjan.h:60
ogdf::Array::init
void init()
Reinitializes the array to an array with empty index set.
Definition: Array.h:372
ogdf::MaxFlowGoldbergTarjan::globalRelabel
void globalRelabel()
Definition: MaxFlowGoldbergTarjan.h:190
ogdf::AdjElement::twin
adjEntry twin() const
Returns the corresponding adjacency element associated with the same edge.
Definition: Graph_d.h:172
ogdf::AdjElement
Class for adjacency list elements.
Definition: Graph_d.h:142
ogdf::EpsilonTest::less
std::enable_if< std::is_integral< T >::value, bool >::type less(const T &x, const T &y) const
Compare if x is LESS than y for integral types.
Definition: EpsilonTest.h:55
ogdf::MaxFlowGoldbergTarjan::m_ex
NodeArray< TCap > m_ex
Definition: MaxFlowGoldbergTarjan.h:62
ogdf::MaxFlowModule< TCap >::m_et
EpsilonTest * m_et
Pointer to the used EpsilonTest.
Definition: MaxFlowModule.h:43
ogdf::MaxFlowGoldbergTarjan::computeFlowAfterValue
void computeFlowAfterValue()
Compute the flow itself after the flow value is already computed. Only used in algorithms with 2 phas...
Definition: MaxFlowGoldbergTarjan.h:370
ogdf::AdjElement::theEdge
edge theEdge() const
Returns the edge associated with this adjacency entry.
Definition: Graph_d.h:160
ogdf::MaxFlowModule< TCap >::m_s
const node * m_s
Pointer to the source node.
Definition: MaxFlowModule.h:47
ogdf::Graph::nodes
internal::GraphObjectContainer< NodeElement > nodes
The container containing all node objects.
Definition: Graph_d.h:932
ogdf::MaxFlowModule< TCap >::m_G
const Graph * m_G
Pointer to the given graph.
Definition: MaxFlowModule.h:45
ogdf::MaxFlowGoldbergTarjan::isAdmissible
bool isAdmissible(const adjEntry adj) const
Definition: MaxFlowGoldbergTarjan.h:88
ogdf::MaxFlowGoldbergTarjan::findNewMaxLabel
void findNewMaxLabel()
Definition: MaxFlowGoldbergTarjan.h:112
ogdf::List::pushFront
iterator pushFront(const E &x)
Adds element x at the beginning of the list.
Definition: List.h:1534
ogdf::MaxFlowGoldbergTarjan::push
void push(const adjEntry adj)
Definition: MaxFlowGoldbergTarjan.h:172
ogdf::Graph::numberOfNodes
int numberOfNodes() const
Returns the number of nodes in the graph.
Definition: Graph_d.h:982
ogdf::MaxFlowGoldbergTarjan::setInactive
void setInactive(const node v)
Definition: MaxFlowGoldbergTarjan.h:118
ogdf::Array
The parameterized class Array implements dynamic arrays of type E.
Definition: Array.h:219
GraphList.h
Decralation of GraphElement and GraphList classes.
ogdf::AdjElement::succ
adjEntry succ() const
Returns the successor in the adjacency list.
Definition: Graph_d.h:218
ogdf::NodeElement::adjEntries
internal::GraphObjectContainer< AdjElement > adjEntries
The container containing all entries in the adjacency list of this node.
Definition: Graph_d.h:271
ogdf::MaxFlowGoldbergTarjan::isResidualEdge
bool isResidualEdge(const adjEntry adj) const
Definition: MaxFlowGoldbergTarjan.h:80
ogdf::Graph::firstNode
node firstNode() const
Returns the first node in the list of all nodes.
Definition: Graph_d.h:997
ogdf::MaxFlowGoldbergTarjan::m_activeLabelList
Array< List< node > > m_activeLabelList
Definition: MaxFlowGoldbergTarjan.h:65
ogdf::EdgeElement::source
node source() const
Returns the source node of the edge.
Definition: Graph_d.h:398
ogdf::List
Doubly linked lists (maintaining the length of the list).
Definition: DfsMakeBiconnected.h:40
ogdf::internal::GraphRegisteredArray
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition: Graph_d.h:658
ogdf::EpsilonTest::greater
std::enable_if< std::is_integral< T >::value, bool >::type greater(const T &x, const T &y) const
Compare if x is GREATER than y for integral types.
Definition: EpsilonTest.h:159
ogdf::MaxFlowGoldbergTarjan::setLabel
void setLabel(const node v, int label)
Definition: MaxFlowGoldbergTarjan.h:127
ogdf::AdjElement::twinNode
node twinNode() const
Returns the associated node of the corresponding adjacency entry (shorthand for twin()->theNode()).
Definition: Graph_d.h:175
ogdf::MaxFlowGoldbergTarjan::relabelStage2
void relabelStage2(const node v)
Definition: MaxFlowGoldbergTarjan.h:228
ogdf::Graph::edges
internal::GraphObjectContainer< EdgeElement > edges
The container containing all edge objects.
Definition: Graph_d.h:935
basic.h
Basic declarations, included by all source files.
ogdf::MaxFlowModule
Definition: MaxFlowModule.h:41
ogdf::NodeElement::firstAdj
adjEntry firstAdj() const
Returns the first entry in the adjaceny list.
Definition: Graph_d.h:286
ogdf::NodeElement::succ
node succ() const
Returns the successor in the list of all nodes.
Definition: Graph_d.h:292
Array.h
Declaration and implementation of Array class and Array algorithms.
ogdf::EdgeElement
Class for the representation of edges.
Definition: Graph_d.h:363
List.h
Declaration of doubly linked lists and iterators.
ogdf::MaxFlowGoldbergTarjan::m_activeLabelListPosition
NodeArray< ListIterator< node > > m_activeLabelListPosition
Definition: MaxFlowGoldbergTarjan.h:64
ogdf::MaxFlowGoldbergTarjan::m_cutNodes
List< node > m_cutNodes
Definition: MaxFlowGoldbergTarjan.h:73
ogdf::MaxFlowGoldbergTarjan::setActive
void setActive(const node v)
Definition: MaxFlowGoldbergTarjan.h:101
ogdf::MaxFlowGoldbergTarjan::m_maxLabel
int m_maxLabel
Definition: MaxFlowGoldbergTarjan.h:66
ogdf::RegisteredArray< GraphRegistry< Key >, Value, WithDefault, Graph >::init
void init(const Graph *base=nullptr)
Reinitializes the array. Associates the array with the matching registry of base.
Definition: RegisteredArray.h:858
ogdf::MaxFlowModule< TCap >::m_cap
const EdgeArray< TCap > * m_cap
Pointer to the given capacity array.
Definition: MaxFlowModule.h:46
ogdf::MaxFlowGoldbergTarjan::computeValue
TCap computeValue(const EdgeArray< TCap > &cap, const node &s, const node &t)
Compute only the value of the flow.
Definition: MaxFlowGoldbergTarjan.h:244
ogdf::EpsilonTest::geq
std::enable_if< std::is_integral< T >::value, bool >::type geq(const T &x, const T &y) const
Compare if x is GEQ to y for integral types.
Definition: EpsilonTest.h:133
ogdf::EdgeElement::target
node target() const
Returns the target node of the edge.
Definition: Graph_d.h:401
ogdf::NodeElement
Class for the representation of nodes.
Definition: Graph_d.h:240
ogdf::MaxFlowModule< TCap >::m_flow
EdgeArray< TCap > * m_flow
Pointer to (extern) flow array.
Definition: MaxFlowModule.h:44
ogdf::List::pushBack
iterator pushBack(const E &x)
Adds element x at the end of the list.
Definition: List.h:1547
ogdf::internal::EdgeArrayBase2
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
Definition: Graph_d.h:716
ogdf::List::clear
void clear()
Removes all elements from the list.
Definition: List.h:1626