lemon/min_mean_cycle.h
changeset 2418 89cbf0a2ed57
parent 2409 fe0a8fe16271
child 2437 02c7076bf894
equal deleted inserted replaced
0:982fbeb22e1d 1:fd4d28f40a3b
    31 namespace lemon {
    31 namespace lemon {
    32 
    32 
    33   /// \addtogroup min_cost_flow
    33   /// \addtogroup min_cost_flow
    34   /// @{
    34   /// @{
    35 
    35 
    36   /// \brief Implementation of Karp's algorithm for finding a 
    36   /// \brief Implementation of Karp's algorithm for finding a
    37   /// minimum mean cycle.
    37   /// minimum mean (directed) cycle.
    38   ///
    38   ///
    39   /// The \ref lemon::MinMeanCycle "MinMeanCycle" implements Karp's 
    39   /// The \ref lemon::MinMeanCycle "MinMeanCycle" implements Karp's
    40   /// algorithm for finding a minimum mean cycle.
    40   /// algorithm for finding a minimum mean (directed) cycle.
    41   ///
    41   ///
    42   /// \param Graph The directed graph type the algorithm runs on.
    42   /// \param Graph The directed graph type the algorithm runs on.
    43   /// \param LengthMap The type of the length (cost) map.
    43   /// \param LengthMap The type of the length (cost) map.
    44   ///
    44   ///
    45   /// \author Peter Kovacs
    45   /// \author Peter Kovacs
    55   {
    55   {
    56     typedef typename Graph::Node Node;
    56     typedef typename Graph::Node Node;
    57     typedef typename Graph::NodeIt NodeIt;
    57     typedef typename Graph::NodeIt NodeIt;
    58     typedef typename Graph::Edge Edge;
    58     typedef typename Graph::Edge Edge;
    59     typedef typename Graph::EdgeIt EdgeIt;
    59     typedef typename Graph::EdgeIt EdgeIt;
    60     typedef typename Graph::InEdgeIt InEdgeIt;
       
    61     typedef typename Graph::OutEdgeIt OutEdgeIt;
    60     typedef typename Graph::OutEdgeIt OutEdgeIt;
    62 
    61 
    63     typedef typename LengthMap::Value Length;
    62     typedef typename LengthMap::Value Length;
    64     
    63 
    65     typedef typename Graph::template NodeMap<int> IntNodeMap;
    64     typedef typename Graph::template NodeMap<int> IntNodeMap;
    66     typedef typename Graph::template NodeMap<Edge> PredNodeMap;
    65     typedef typename Graph::template NodeMap<Edge> PredNodeMap;
    67     typedef Path<Graph> Path;
    66     typedef Path<Graph> Path;
    68     typedef std::vector<Node> NodeVector;
    67     typedef std::vector<Node> NodeVector;
    69     typedef typename NodeVector::iterator NodeVectorIt;
    68     typedef typename NodeVector::iterator NodeVectorIt;
    70 
    69 
    71   protected:
    70   protected:
    72   
    71 
    73     /// \brief Data sturcture for path data.
    72     /// \brief Data sturcture for path data.
    74     struct PathData {
    73     struct PathData
       
    74     {
    75       bool found;
    75       bool found;
    76       Length dist;
    76       Length dist;
    77       Edge pred;
    77       Edge pred;
    78       PathData(bool _found = false, Length _dist = 0) : 
    78       PathData(bool _found = false, Length _dist = 0) :
    79 	found(_found), dist(_dist), pred(INVALID) {}
    79 	found(_found), dist(_dist), pred(INVALID) {}
    80       PathData(bool _found, Length _dist, Edge _pred) : 
    80       PathData(bool _found, Length _dist, Edge _pred) :
    81 	found(_found), dist(_dist), pred(_pred) {}
    81 	found(_found), dist(_dist), pred(_pred) {}
    82     };
    82     };
    83     
    83 
    84   private:
    84   private:
    85   
    85 
    86     typedef typename Graph::template NodeMap<std::vector<PathData> > PathVectorNodeMap;
    86     typedef typename Graph::template NodeMap<std::vector<PathData> >
    87   
    87       PathDataNodeMap;
       
    88 
    88   protected:
    89   protected:
    89 
    90 
    90     /// \brief Node map for storing path data.
    91     /// \brief Node map for storing path data.
    91     /// 
    92     /// 
    92     /// Node map for storing path data of all nodes in the current
    93     /// Node map for storing path data of all nodes in the current
    93     /// component. dmap[v][k] is the length of a shortest directed walk 
    94     /// component. dmap[v][k] is the length of a shortest directed walk 
    94     /// to node v from the starting node containing exactly k edges.
    95     /// to node v from the starting node containing exactly k edges.
    95     PathVectorNodeMap dmap;
    96     PathDataNodeMap dmap;
    96     
    97     
    97     /// \brief The directed graph the algorithm runs on.
    98     /// \brief The directed graph the algorithm runs on.
    98     const Graph& graph;
    99     const Graph& graph;
    99     /// \brief The length of the edges.
   100     /// \brief The length of the edges.
   100     const LengthMap& length;
   101     const LengthMap& length;
   101     
   102     
   102     /// \brief The total length of the found cycle.
   103     /// \brief The total length of the found cycle.
   103     Length cycle_length;
   104     Length cycle_length;
   104     /// \brief The number of edges in the found cycle.
   105     /// \brief The number of edges in the found cycle.
   105     int cycle_size;
   106     int cycle_size;
       
   107     /// \brief A node for obtaining a minimum mean cycle. 
       
   108     Node cycle_node;
       
   109 
   106     /// \brief The found cycle.
   110     /// \brief The found cycle.
   107     Path *cycle_path;
   111     Path *cycle_path;
   108     /// \brief The found cycle.
   112     /// \brief The algorithm uses local \ref lemon::Path "Path" 
       
   113     /// structure to store the found cycle.
   109     bool local_path;
   114     bool local_path;
   110     
   115     
   111     /// \brief Node map for identifying strongly connected components.
   116     /// \brief Node map for identifying strongly connected components.
   112     IntNodeMap comp;
   117     IntNodeMap comp;
   113     /// \brief The number of strongly connected components.
   118     /// \brief The number of strongly connected components.
   114     int comp_num;
   119     int comp_num;
   115     /// \brief %Counter for identifying the current component.
   120     /// \brief Counter for identifying the current component.
   116     int comp_cnt;
   121     int comp_cnt;
   117     /// \brief Nodes of the current component.
   122     /// \brief Nodes of the current component.
   118     NodeVector nodes;
   123     NodeVector nodes;
   119     /// \brief The processed nodes in the last round.
   124     /// \brief The processed nodes in the last round.
   120     NodeVector process;
   125     NodeVector process;
   127     ///
   132     ///
   128     /// \param _graph The directed graph the algorithm runs on.
   133     /// \param _graph The directed graph the algorithm runs on.
   129     /// \param _length The length (cost) of the edges.
   134     /// \param _length The length (cost) of the edges.
   130     MinMeanCycle( const Graph& _graph,
   135     MinMeanCycle( const Graph& _graph,
   131 		  const LengthMap& _length ) :
   136 		  const LengthMap& _length ) :
   132       graph(_graph), length(_length), dmap(_graph), 
   137       graph(_graph), length(_length), dmap(_graph), comp(_graph),
   133       cycle_length(0), cycle_size(-1), comp(_graph),
   138       cycle_length(0), cycle_size(-1), cycle_node(INVALID),
   134       cycle_path(NULL), local_path(false)
   139       cycle_path(NULL), local_path(false)
   135     { }
   140     { }
   136 
   141 
   137     /// \brief The destructor of the class.
   142     /// \brief The destructor of the class.
   138     ~MinMeanCycle() { 
   143     ~MinMeanCycle() { 
   139       if (local_path) delete cycle_path;
   144       if (local_path) delete cycle_path;
   140     }
   145     }
   141 
   146 
   142   protected:
   147   protected:
   143     
       
   144     /// \brief Initializes the internal data structures.
       
   145     void init() {
       
   146       comp_num = stronglyConnectedComponents(graph, comp);
       
   147       if (!cycle_path) {
       
   148 	local_path = true;
       
   149 	cycle_path = new Path;
       
   150       }
       
   151     }
       
   152 
   148 
   153     /// \brief Initializes the internal data structures for the current
   149     /// \brief Initializes the internal data structures for the current
   154     /// component.
   150     /// component.
   155     void initCurrent() {
   151     void initCurrent() {
   156       nodes.clear();
   152       nodes.clear();
   157       // Finding the nodes of the current component
   153       // Finding the nodes of the current component
   158       for (NodeIt v(graph); v != INVALID; ++v) {
   154       for (NodeIt v(graph); v != INVALID; ++v) {
   159 	if (comp[v] == comp_cnt) nodes.push_back(v);
   155 	if (comp[v] == comp_cnt) nodes.push_back(v);
   160       }
   156       }
   161 
       
   162       // Creating vectors for all nodes
   157       // Creating vectors for all nodes
   163       int n = nodes.size();
   158       int n = nodes.size();
   164       for (NodeVectorIt vi = nodes.begin(); vi != nodes.end(); ++vi) {
   159       for (NodeVectorIt vi = nodes.begin(); vi != nodes.end(); ++vi) {
   165 	dmap[*vi].resize(n + 1);
   160 	dmap[*vi].resize(n + 1);
   166       }
   161       }
   167     }
   162     }
   168     
   163     
   169     /// \brief Processes all rounds of computing required path data.
   164     /// \brief Processes all rounds of computing required path data for 
       
   165     /// the current component.
   170     void processRounds() {
   166     void processRounds() {
   171       dmap[nodes[0]][0] = PathData(true, 0);
   167       dmap[nodes[0]][0] = PathData(true, 0);
   172       process.clear();
   168       process.clear();
   173       for (OutEdgeIt oe(graph, nodes[0]); oe != INVALID; ++oe) {
   169       // Processing the first round
   174 	Node v = graph.target(oe);
   170       for (OutEdgeIt e(graph, nodes[0]); e != INVALID; ++e) {
       
   171 	Node v = graph.target(e);
   175 	if (comp[v] != comp_cnt || v == nodes[0]) continue;
   172 	if (comp[v] != comp_cnt || v == nodes[0]) continue;
   176 	dmap[v][1] = PathData(true, length[oe], oe);
   173 	dmap[v][1] = PathData(true, length[e], e);
   177 	process.push_back(v);
   174 	process.push_back(v);
   178       }
   175       }
       
   176       // Processing other rounds 
   179       int n = nodes.size(), k;
   177       int n = nodes.size(), k;
   180       for (k = 2; k <= n && process.size() < n; ++k) {
   178       for (k = 2; k <= n && process.size() < n; ++k) {
   181 	processNextBuildRound(k);
   179 	processNextBuildRound(k);
   182       }
   180       }
   183       for ( ; k <= n; ++k) {
   181       for ( ; k <= n; ++k) {
   188     /// \brief Processes one round of computing required path data and
   186     /// \brief Processes one round of computing required path data and
   189     /// rebuilds \ref process vector.
   187     /// rebuilds \ref process vector.
   190     void processNextBuildRound(int k) {
   188     void processNextBuildRound(int k) {
   191       NodeVector next;
   189       NodeVector next;
   192       for (NodeVectorIt ui = process.begin(); ui != process.end(); ++ui) {
   190       for (NodeVectorIt ui = process.begin(); ui != process.end(); ++ui) {
   193 	for (OutEdgeIt oe(graph, *ui); oe != INVALID; ++oe) {
   191 	for (OutEdgeIt e(graph, *ui); e != INVALID; ++e) {
   194 	  Node v = graph.target(oe);
   192 	  Node v = graph.target(e);
   195 	  if (comp[v] != comp_cnt) continue;
   193 	  if (comp[v] != comp_cnt) continue;
   196 	  if ( !dmap[v][k].found || (dmap[v][k].dist > dmap[*ui][k-1].dist + length[oe]) ) {
   194 	  if (!dmap[v][k].found) {
   197 	    if (!dmap[v][k].found) next.push_back(v); 
   195 	    next.push_back(v);
   198 	    dmap[v][k] = PathData(true, dmap[*ui][k-1].dist + length[oe], oe);
   196 	    dmap[v][k] = PathData(true, dmap[*ui][k-1].dist + length[e], e);
       
   197 	  }
       
   198 	  else if (dmap[*ui][k-1].dist + length[e] < dmap[v][k].dist) {
       
   199 	    dmap[v][k] = PathData(true, dmap[*ui][k-1].dist + length[e], e);
   199 	  }
   200 	  }
   200 	}
   201 	}
   201       }
   202       }
   202       process.swap(next);
   203       process.swap(next);
   203     }
   204     }
   204 
   205 
   205     /// \brief Processes one round of computing required path data
   206     /// \brief Processes one round of computing required path data
   206     /// using \ref nodes vector instead of \ref process vector.
   207     /// using \ref nodes vector instead of \ref process vector.
   207     void processNextFullRound(int k) {
   208     void processNextFullRound(int k) {
   208       for (NodeVectorIt ui = nodes.begin(); ui != nodes.end(); ++ui) {
   209       for (NodeVectorIt ui = nodes.begin(); ui != nodes.end(); ++ui) {
   209 	for (OutEdgeIt oe(graph, *ui); oe != INVALID; ++oe) {
   210 	for (OutEdgeIt e(graph, *ui); e != INVALID; ++e) {
   210 	  Node v = graph.target(oe);
   211 	  Node v = graph.target(e);
   211 	  if (comp[v] != comp_cnt) continue;
   212 	  if (comp[v] != comp_cnt) continue;
   212 	  if ( !dmap[v][k].found || (dmap[v][k].dist > dmap[*ui][k-1].dist + length[oe]) ) {
   213 	  if ( !dmap[v][k].found || 
   213 	    dmap[v][k] = PathData(true, dmap[*ui][k-1].dist + length[oe], oe);
   214 	       dmap[*ui][k-1].dist + length[e] < dmap[v][k].dist ) {
       
   215 	    dmap[v][k] = PathData(true, dmap[*ui][k-1].dist + length[e], e);
   214 	  }
   216 	  }
   215 	}
   217 	}
   216       }
   218       }
   217     }
   219     }
   218     
   220     
   219     /// \brief Finds the minimum cycle mean value according to the path
   221     /// \brief Finds the minimum cycle mean value in the current 
   220     /// data stored in \ref dmap.
   222     /// component.
   221     ///
   223     bool findCurrentMin(Length &min_length, int &min_size, Node &min_node) {
   222     /// Finds the minimum cycle mean value according to the path data
       
   223     /// stored in \ref dmap.
       
   224     ///
       
   225     /// \retval min_length The total length of the found cycle.
       
   226     /// \retval min_size The number of edges in the found cycle.
       
   227     /// \retval min_node A node for obtaining a critical cycle.
       
   228     ///
       
   229     /// \return \c true if a cycle exists in the graph.
       
   230     bool findMinCycleMean(Length &min_length, int &min_size, Node &min_node) {
       
   231       bool found_min = false;
   224       bool found_min = false;
   232       for (NodeVectorIt vi = nodes.begin(); vi != nodes.end(); ++vi) {
   225       for (NodeVectorIt vi = nodes.begin(); vi != nodes.end(); ++vi) {
       
   226 	int n = nodes.size();
       
   227 	if (!dmap[*vi][n].found) continue;
   233 	Length len;
   228 	Length len;
   234 	int size;
   229 	int size;
   235 	bool found_one = false;
   230 	bool found_one = false;
   236 	int n = nodes.size();
       
   237 	for (int k = 0; k < n; ++k) {
   231 	for (int k = 0; k < n; ++k) {
       
   232 	  if (!dmap[*vi][k].found) continue;
   238 	  Length _len = dmap[*vi][n].dist - dmap[*vi][k].dist;
   233 	  Length _len = dmap[*vi][n].dist - dmap[*vi][k].dist;
   239 	  int _size = n - k; 
   234 	  int _size = n - k; 
   240 	  if ( dmap[*vi][n].found && dmap[*vi][k].found && (!found_one || len * _size < _len * size) ) {
   235 	  if (!found_one || len * _size < _len * size) {
   241 	    found_one = true;
   236 	    found_one = true;
   242 	    len = _len;
   237 	    len = _len;
   243 	    size = _size;
   238 	    size = _size;
   244 	  }
   239 	  }
   245 	}
   240 	}
   246 	if (found_one && (!found_min || len * min_size < min_length * size)) {
   241 	if ( found_one && 
       
   242 	     (!found_min || len * min_size < min_length * size) ) {
   247 	  found_min = true;
   243 	  found_min = true;
   248 	  min_length = len;
   244 	  min_length = len;
   249 	  min_size = size;
   245 	  min_size = size;
   250 	  min_node = *vi;
   246 	  min_node = *vi;
   251 	}
   247 	}
   252       }
   248       }
   253       return found_min;
   249       return found_min;
   254     }
   250     }
   255     
   251     
   256     /// \brief Finds a critical (minimum mean) cycle according to the
   252   public:  
   257     /// path data stored in \ref dmap.
   253     
   258     void findCycle(const Node &min_n) {
       
   259       IntNodeMap reached(graph, -1);
       
   260       int r = reached[min_n] = dmap[min_n].size() - 1;
       
   261       Node u = graph.source(dmap[min_n][r].pred);
       
   262       while (reached[u] < 0) {
       
   263 	reached[u] = --r;
       
   264 	u = graph.source(dmap[u][r].pred);
       
   265       }
       
   266       r = reached[u];
       
   267       Edge ce = dmap[u][r].pred;
       
   268       cycle_path->addFront(ce);
       
   269       Node v;
       
   270       while ((v = graph.source(ce)) != u) {
       
   271 	ce = dmap[v][--r].pred;
       
   272 	cycle_path->addFront(ce);
       
   273       }
       
   274     }
       
   275     
       
   276   public:
       
   277 
       
   278     /// \brief Runs the algorithm.
   254     /// \brief Runs the algorithm.
   279     ///
   255     ///
   280     /// Runs the algorithm.
   256     /// Runs the algorithm.
   281     ///
   257     ///
   282     /// \return \c true if a cycle exists in the graph.
   258     /// \return \c true if a cycle exists in the graph.
       
   259     ///
       
   260     /// \note Apart from the return value, m.run() is just a shortcut 
       
   261     /// of the following code.
       
   262     /// \code
       
   263     ///   m.init();
       
   264     ///   m.findMinMean();
       
   265     ///   m.findCycle();
       
   266     /// \endcode
   283     bool run() {
   267     bool run() {
   284       init();
   268       init();
   285       // Searching for the minimum mean cycle in all components
   269       findMinMean();
   286       bool found_cycle = false;
   270       return findCycle();
   287       Node cycle_node;
   271     }
       
   272     
       
   273     /// \brief Initializes the internal data structures.
       
   274     void init() {
       
   275       comp_num = stronglyConnectedComponents(graph, comp);
       
   276       if (!cycle_path) {
       
   277 	local_path = true;
       
   278 	cycle_path = new Path;
       
   279       }
       
   280     }
       
   281 
       
   282     /// \brief Finds the minimum cycle mean value in the graph.
       
   283     ///
       
   284     /// Computes all the required path data and finds the minimum cycle
       
   285     /// mean value in the graph.
       
   286     ///
       
   287     /// \return \c true if a cycle exists in the graph.
       
   288     /// 
       
   289     /// \pre \ref init() must be called before using this function.
       
   290     bool findMinMean() {
       
   291       cycle_node = INVALID;
   288       for (comp_cnt = 0; comp_cnt < comp_num; ++comp_cnt) {
   292       for (comp_cnt = 0; comp_cnt < comp_num; ++comp_cnt) {
   289       
       
   290 	initCurrent();
   293 	initCurrent();
   291 	processRounds();
   294 	processRounds();
   292 	
   295 	
   293 	Length min_length;
   296 	Length min_length;
   294 	int min_size;
   297 	int min_size;
   295 	Node min_node;
   298 	Node min_node;
   296 	bool found_min = findMinCycleMean(min_length, min_size, min_node);
   299 	bool found_min = findCurrentMin(min_length, min_size, min_node);
   297 	
   300 	
   298 	if ( found_min && (!found_cycle || min_length * cycle_size  < cycle_length * min_size) ) {
   301 	if ( found_min && (cycle_node == INVALID || 
   299 	  found_cycle = true;
   302 	     min_length * cycle_size < cycle_length * min_size) ) {
   300 	  cycle_length = min_length;
   303 	  cycle_length = min_length;
   301 	  cycle_size = min_size;
   304 	  cycle_size = min_size;
   302 	  cycle_node = min_node;
   305 	  cycle_node = min_node;
   303 	}
   306 	}
   304       }
   307       }
   305       if (found_cycle) findCycle(cycle_node);
   308       return (cycle_node != INVALID);
   306       return found_cycle;
   309     }
   307     }
   310     
   308     
   311     /// \brief Finds a critical (minimum mean) cycle.
   309     /// \brief Returns the total length of the found critical cycle.
   312     ///
   310     ///
   313     /// Finds a critical (minimum mean) cycle using the path data
   311     /// Returns the total length of the found critical cycle.
   314     /// stored in \ref dmap.
       
   315     ///
       
   316     /// \return \c true if a cycle exists in the graph.
       
   317     /// 
       
   318     /// \pre \ref init() and \ref findMinMean() must be called before 
       
   319     /// using this function.
       
   320     bool findCycle() {
       
   321       if (cycle_node == INVALID) return false;
       
   322       cycle_length = 0;
       
   323       cycle_size = 0;
       
   324       IntNodeMap reached(graph, -1);
       
   325       int r = reached[cycle_node] = dmap[cycle_node].size() - 1;
       
   326       Node u = graph.source(dmap[cycle_node][r].pred);
       
   327       while (reached[u] < 0) {
       
   328 	reached[u] = --r;
       
   329 	u = graph.source(dmap[u][r].pred);
       
   330       }
       
   331       r = reached[u];
       
   332       Edge e = dmap[u][r].pred;
       
   333       cycle_path->addFront(e);
       
   334       cycle_length = cycle_length + length[e];
       
   335       ++cycle_size;
       
   336       Node v;
       
   337       while ((v = graph.source(e)) != u) {
       
   338 	e = dmap[v][--r].pred;
       
   339 	cycle_path->addFront(e);
       
   340 	cycle_length = cycle_length + length[e];
       
   341 	++cycle_size;
       
   342       }
       
   343       return true;
       
   344     }
       
   345 
       
   346     /// \brief Resets the internal data structures.
       
   347     ///
       
   348     /// Resets the internal data structures so that \ref findMinMean() 
       
   349     /// and \ref findCycle() can be called again (e.g. when the 
       
   350     /// underlaying graph has been modified).
       
   351     void reset() {
       
   352       for (NodeIt u(graph); u != INVALID; ++u)
       
   353 	dmap[u].clear();
       
   354       cycle_node = INVALID;
       
   355       if (cycle_path) cycle_path->clear();
       
   356       comp_num = stronglyConnectedComponents(graph, comp);
       
   357     }
       
   358     
       
   359     /// \brief Returns the total length of the found cycle.
       
   360     ///
       
   361     /// Returns the total length of the found cycle.
   312     ///
   362     ///
   313     /// \pre \ref run() must be called before using this function.
   363     /// \pre \ref run() must be called before using this function.
   314     Length cycleLength() const { 
   364     Length cycleLength() const { 
   315       return cycle_length;
   365       return cycle_length;
   316     }
   366     }
   317     
   367     
   318     /// \brief Returns the number of edges in the found critical 
   368     /// \brief Returns the number of edges in the found cycle.
   319     /// cycle.
   369     ///
   320     ///
   370     /// Returns the number of edges in the found cycle.
   321     /// Returns the number of edges in the found critical cycle.
       
   322     ///
   371     ///
   323     /// \pre \ref run() must be called before using this function.
   372     /// \pre \ref run() must be called before using this function.
   324     int cycleEdgeNum() const { 
   373     int cycleEdgeNum() const { 
   325       return cycle_size;
   374       return cycle_size;
   326     }
   375     }
   327     
   376     
   328     /// \brief Returns the mean length of the found critical cycle.
   377     /// \brief Returns the mean length of the found cycle.
   329     ///
   378     ///
   330     /// Returns the mean length of the found critical cycle.
   379     /// Returns the mean length of the found cycle.
   331     ///
   380     ///
   332     /// \pre \ref run() must be called before using this function.
   381     /// \pre \ref run() must be called before using this function.
   333     ///
   382     ///
   334     /// \warning LengthMap::Value must be convertible to double.
   383     /// \warning LengthMap::Value must be convertible to double.
       
   384     ///
       
   385     /// \note m.minMean() is just a shortcut of the following code.
       
   386     /// \code
       
   387     ///   return m.cycleEdgeNum() / double(m.cycleLength());
       
   388     /// \endcode
   335     double minMean() const { 
   389     double minMean() const { 
   336       return (double)cycle_length / (double)cycle_size;
   390       return cycle_length / (double)cycle_size;
   337     }
   391     }
   338 
   392 
   339     /// \brief Returns a const reference to the \ref lemon::Path "Path"
   393     /// \brief Returns a const reference to the \ref lemon::Path "Path"
   340     /// structure of the found flow.
   394     /// structure of the found cycle.
   341     ///
   395     ///
   342     /// Returns a const reference to the \ref lemon::Path "Path"
   396     /// Returns a const reference to the \ref lemon::Path "Path"
   343     /// structure of the found flow.
   397     /// structure of the found cycle.
   344     ///
   398     ///
   345     /// \pre \ref run() must be called before using this function.
   399     /// \pre \ref run() must be called before using this function.
   346     ///
   400     ///
   347     /// \sa \ref cyclePath()
   401     /// \sa \ref cyclePath()
   348     const Path &cycle() const {
   402     const Path &cycle() const {