Index: lemon/network_simplex.h
===================================================================
--- lemon/network_simplex.h	(revision 1026)
+++ lemon/network_simplex.h	(revision 1081)
@@ -3,5 +3,5 @@
  * This file is a part of LEMON, a generic C++ optimization library.
  *
- * Copyright (C) 2003-2010
+ * Copyright (C) 2003-2011
  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
  * (Egervary Research Group on Combinatorial Optimization, EGRES).
@@ -41,15 +41,13 @@
   ///
   /// \ref NetworkSimplex implements the primal Network Simplex algorithm
-  /// for finding a \ref min_cost_flow "minimum cost flow"
-  /// \ref amo93networkflows, \ref dantzig63linearprog,
-  /// \ref kellyoneill91netsimplex.
-  /// This algorithm is a highly efficient specialized version of the
-  /// linear programming simplex method directly for the minimum cost
-  /// flow problem.
+  /// for finding a \ref min_cost_flow "minimum cost flow".
+  /// This algorithm is a specialized version of the linear programming
+  /// simplex method directly for the minimum cost flow problem.
+  /// It is one of the most efficient solution methods.
   ///
-  /// In general, \ref NetworkSimplex and \ref CostScaling are the fastest
-  /// implementations available in LEMON for this problem.
-  /// Furthermore, this class supports both directions of the supply/demand
-  /// inequality constraints. For more information, see \ref SupplyType.
+  /// In general this class is the fastest implementation available
+  /// in LEMON for the minimum cost flow problem.
+  /// Moreover it supports both directions of the supply/demand inequality
+  /// constraints. For more information see \ref SupplyType.
   ///
   /// Most of the parameters of the problem (except for the digraph)
@@ -59,16 +57,15 @@
   ///
   /// \tparam GR The digraph type the algorithm runs on.
-  /// \tparam V The number type used for flow amounts, capacity bounds
-  /// and supply values in the algorithm. By default, it is \c int.
-  /// \tparam C The number type used for costs and potentials in the
-  /// algorithm. By default, it is the same as \c V.
+  /// \tparam V The value type used for flow amounts, capacity bounds
+  /// and supply values in the algorithm. By default it is \c int.
+  /// \tparam C The value type used for costs and potentials in the
+  /// algorithm. By default it is the same as \c V.
   ///
-  /// \warning Both \c V and \c C must be signed number types.
-  /// \warning All input data (capacities, supply values, and costs) must
+  /// \warning Both value types must be signed and all input data must
   /// be integer.
   ///
   /// \note %NetworkSimplex provides five different pivot rule
   /// implementations, from which the most efficient one is used
-  /// by default. For more information, see \ref PivotRule.
+  /// by default. For more information see \ref PivotRule.
   template <typename GR, typename V = int, typename C = V>
   class NetworkSimplex
@@ -126,21 +123,21 @@
     /// implementations that significantly affect the running time
     /// of the algorithm.
-    /// By default, \ref BLOCK_SEARCH "Block Search" is used, which
-    /// turend out to be the most efficient and the most robust on various
-    /// test inputs.
-    /// However, another pivot rule can be selected using the \ref run()
+    /// By default \ref BLOCK_SEARCH "Block Search" is used, which
+    /// proved to be the most efficient and the most robust on various
+    /// test inputs according to our benchmark tests.
+    /// However another pivot rule can be selected using the \ref run()
     /// function with the proper parameter.
     enum PivotRule {
 
-      /// The \e First \e Eligible pivot rule.
+      /// The First Eligible pivot rule.
       /// The next eligible arc is selected in a wraparound fashion
       /// in every iteration.
       FIRST_ELIGIBLE,
 
-      /// The \e Best \e Eligible pivot rule.
+      /// The Best Eligible pivot rule.
       /// The best eligible arc is selected in every iteration.
       BEST_ELIGIBLE,
 
-      /// The \e Block \e Search pivot rule.
+      /// The Block Search pivot rule.
       /// A specified number of arcs are examined in every iteration
       /// in a wraparound fashion and the best eligible arc is selected
@@ -148,5 +145,5 @@
       BLOCK_SEARCH,
 
-      /// The \e Candidate \e List pivot rule.
+      /// The Candidate List pivot rule.
       /// In a major iteration a candidate list is built from eligible arcs
       /// in a wraparound fashion and in the following minor iterations
@@ -154,5 +151,5 @@
       CANDIDATE_LIST,
 
-      /// The \e Altering \e Candidate \e List pivot rule.
+      /// The Altering Candidate List pivot rule.
       /// It is a modified version of the Candidate List method.
       /// It keeps only the several best eligible arcs from the former
@@ -165,22 +162,16 @@
     TEMPLATE_DIGRAPH_TYPEDEFS(GR);
 
+    typedef std::vector<Arc> ArcVector;
+    typedef std::vector<Node> NodeVector;
     typedef std::vector<int> IntVector;
+    typedef std::vector<bool> BoolVector;
     typedef std::vector<Value> ValueVector;
     typedef std::vector<Cost> CostVector;
-    typedef std::vector<signed char> CharVector;
-    // Note: vector<signed char> is used instead of vector<ArcState> and
-    // vector<ArcDirection> for efficiency reasons
 
     // State constants for arcs
-    enum ArcState {
+    enum ArcStateEnum {
       STATE_UPPER = -1,
       STATE_TREE  =  0,
       STATE_LOWER =  1
-    };
-
-    // Direction constants for tree arcs
-    enum ArcDirection {
-      DIR_DOWN = -1,
-      DIR_UP   =  1
     };
 
@@ -204,5 +195,4 @@
     IntVector _source;
     IntVector _target;
-    bool _arc_mixing;
 
     // Node and arc data
@@ -222,14 +212,14 @@
     IntVector _succ_num;
     IntVector _last_succ;
-    CharVector _pred_dir;
-    CharVector _state;
     IntVector _dirty_revs;
+    BoolVector _forward;
+    IntVector _state;
     int _root;
 
     // Temporary data used in the current pivot iteration
     int in_arc, join, u_in, v_in, u_out, v_out;
+    int first, second, right, last;
+    int stem, par_stem, new_stem;
     Value delta;
-
-    const Value MAX;
 
   public:
@@ -253,5 +243,5 @@
       const IntVector  &_target;
       const CostVector &_cost;
-      const CharVector &_state;
+      const IntVector  &_state;
       const CostVector &_pi;
       int &_in_arc;
@@ -274,5 +264,5 @@
       bool findEnteringArc() {
         Cost c;
-        for (int e = _next_arc; e != _search_arc_num; ++e) {
+        for (int e = _next_arc; e < _search_arc_num; ++e) {
           c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
           if (c < 0) {
@@ -282,5 +272,5 @@
           }
         }
-        for (int e = 0; e != _next_arc; ++e) {
+        for (int e = 0; e < _next_arc; ++e) {
           c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
           if (c < 0) {
@@ -305,5 +295,5 @@
       const IntVector  &_target;
       const CostVector &_cost;
-      const CharVector &_state;
+      const IntVector  &_state;
       const CostVector &_pi;
       int &_in_arc;
@@ -322,5 +312,5 @@
       bool findEnteringArc() {
         Cost c, min = 0;
-        for (int e = 0; e != _search_arc_num; ++e) {
+        for (int e = 0; e < _search_arc_num; ++e) {
           c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
           if (c < min) {
@@ -344,5 +334,5 @@
       const IntVector  &_target;
       const CostVector &_cost;
-      const CharVector &_state;
+      const IntVector  &_state;
       const CostVector &_pi;
       int &_in_arc;
@@ -363,5 +353,5 @@
       {
         // The main parameters of the pivot rule
-        const double BLOCK_SIZE_FACTOR = 1.0;
+        const double BLOCK_SIZE_FACTOR = 0.5;
         const int MIN_BLOCK_SIZE = 10;
 
@@ -375,30 +365,31 @@
         Cost c, min = 0;
         int cnt = _block_size;
-        int e;
-        for (e = _next_arc; e != _search_arc_num; ++e) {
+        int e, min_arc = _next_arc;
+        for (e = _next_arc; e < _search_arc_num; ++e) {
           c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
           if (c < min) {
             min = c;
-            _in_arc = e;
+            min_arc = e;
           }
           if (--cnt == 0) {
-            if (min < 0) goto search_end;
+            if (min < 0) break;
             cnt = _block_size;
           }
         }
-        for (e = 0; e != _next_arc; ++e) {
-          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
-          if (c < min) {
-            min = c;
-            _in_arc = e;
-          }
-          if (--cnt == 0) {
-            if (min < 0) goto search_end;
-            cnt = _block_size;
+        if (min == 0 || cnt > 0) {
+          for (e = 0; e < _next_arc; ++e) {
+            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
+            if (c < min) {
+              min = c;
+              min_arc = e;
+            }
+            if (--cnt == 0) {
+              if (min < 0) break;
+              cnt = _block_size;
+            }
           }
         }
         if (min >= 0) return false;
-
-      search_end:
+        _in_arc = min_arc;
         _next_arc = e;
         return true;
@@ -417,5 +408,5 @@
       const IntVector  &_target;
       const CostVector &_cost;
-      const CharVector &_state;
+      const IntVector  &_state;
       const CostVector &_pi;
       int &_in_arc;
@@ -438,5 +429,5 @@
       {
         // The main parameters of the pivot rule
-        const double LIST_LENGTH_FACTOR = 0.25;
+        const double LIST_LENGTH_FACTOR = 1.0;
         const int MIN_LIST_LENGTH = 10;
         const double MINOR_LIMIT_FACTOR = 0.1;
@@ -455,5 +446,5 @@
       bool findEnteringArc() {
         Cost min, c;
-        int e;
+        int e, min_arc = _next_arc;
         if (_curr_length > 0 && _minor_count < _minor_limit) {
           // Minor iteration: select the best eligible arc from the
@@ -466,11 +457,14 @@
             if (c < min) {
               min = c;
-              _in_arc = e;
+              min_arc = e;
             }
-            else if (c >= 0) {
+            if (c >= 0) {
               _candidates[i--] = _candidates[--_curr_length];
             }
           }
-          if (min < 0) return true;
+          if (min < 0) {
+            _in_arc = min_arc;
+            return true;
+          }
         }
 
@@ -478,5 +472,5 @@
         min = 0;
         _curr_length = 0;
-        for (e = _next_arc; e != _search_arc_num; ++e) {
+        for (e = _next_arc; e < _search_arc_num; ++e) {
           c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
           if (c < 0) {
@@ -484,24 +478,25 @@
             if (c < min) {
               min = c;
-              _in_arc = e;
+              min_arc = e;
             }
-            if (_curr_length == _list_length) goto search_end;
-          }
-        }
-        for (e = 0; e != _next_arc; ++e) {
-          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
-          if (c < 0) {
-            _candidates[_curr_length++] = e;
-            if (c < min) {
-              min = c;
-              _in_arc = e;
+            if (_curr_length == _list_length) break;
+          }
+        }
+        if (_curr_length < _list_length) {
+          for (e = 0; e < _next_arc; ++e) {
+            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
+            if (c < 0) {
+              _candidates[_curr_length++] = e;
+              if (c < min) {
+                min = c;
+                min_arc = e;
+              }
+              if (_curr_length == _list_length) break;
             }
-            if (_curr_length == _list_length) goto search_end;
           }
         }
         if (_curr_length == 0) return false;
-
-      search_end:
         _minor_count = 1;
+        _in_arc = min_arc;
         _next_arc = e;
         return true;
@@ -520,5 +515,5 @@
       const IntVector  &_target;
       const CostVector &_cost;
-      const CharVector &_state;
+      const IntVector  &_state;
       const CostVector &_pi;
       int &_in_arc;
@@ -555,5 +550,5 @@
       {
         // The main parameters of the pivot rule
-        const double BLOCK_SIZE_FACTOR = 1.0;
+        const double BLOCK_SIZE_FACTOR = 1.5;
         const int MIN_BLOCK_SIZE = 10;
         const double HEAD_LENGTH_FACTOR = 0.1;
@@ -573,11 +568,9 @@
         // Check the current candidate list
         int e;
-        Cost c;
-        for (int i = 0; i != _curr_length; ++i) {
+        for (int i = 0; i < _curr_length; ++i) {
           e = _candidates[i];
-          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
-          if (c < 0) {
-            _cand_cost[e] = c;
-          } else {
+          _cand_cost[e] = _state[e] *
+            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
+          if (_cand_cost[e] >= 0) {
             _candidates[i--] = _candidates[--_curr_length];
           }
@@ -586,33 +579,37 @@
         // Extend the list
         int cnt = _block_size;
+        int last_arc = 0;
         int limit = _head_length;
 
-        for (e = _next_arc; e != _search_arc_num; ++e) {
-          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
-          if (c < 0) {
-            _cand_cost[e] = c;
-            _candidates[_curr_length++] = e;
-          }
-          if (--cnt == 0) {
-            if (_curr_length > limit) goto search_end;
-            limit = 0;
-            cnt = _block_size;
-          }
-        }
-        for (e = 0; e != _next_arc; ++e) {
+        for (int e = _next_arc; e < _search_arc_num; ++e) {
           _cand_cost[e] = _state[e] *
             (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
           if (_cand_cost[e] < 0) {
             _candidates[_curr_length++] = e;
+            last_arc = e;
           }
           if (--cnt == 0) {
-            if (_curr_length > limit) goto search_end;
+            if (_curr_length > limit) break;
             limit = 0;
             cnt = _block_size;
           }
         }
+        if (_curr_length <= limit) {
+          for (int e = 0; e < _next_arc; ++e) {
+            _cand_cost[e] = _state[e] *
+              (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
+            if (_cand_cost[e] < 0) {
+              _candidates[_curr_length++] = e;
+              last_arc = e;
+            }
+            if (--cnt == 0) {
+              if (_curr_length > limit) break;
+              limit = 0;
+              cnt = _block_size;
+            }
+          }
+        }
         if (_curr_length == 0) return false;
-
-      search_end:
+        _next_arc = last_arc + 1;
 
         // Make heap of the candidate list (approximating a partial sort)
@@ -622,5 +619,4 @@
         // Pop the first element of the heap
         _in_arc = _candidates[0];
-        _next_arc = e;
         pop_heap( _candidates.begin(), _candidates.begin() + _curr_length,
                   _sort_func );
@@ -638,17 +634,11 @@
     ///
     /// \param graph The digraph the algorithm runs on.
-    /// \param arc_mixing Indicate if the arcs will be stored in a
-    /// mixed order in the internal data structure.
-    /// In general, it leads to similar performance as using the original
-    /// arc order, but it makes the algorithm more robust and in special
-    /// cases, even significantly faster. Therefore, it is enabled by default.
-    NetworkSimplex(const GR& graph, bool arc_mixing = true) :
+    NetworkSimplex(const GR& graph) :
       _graph(graph), _node_id(graph), _arc_id(graph),
-      _arc_mixing(arc_mixing),
-      MAX(std::numeric_limits<Value>::max()),
       INF(std::numeric_limits<Value>::has_infinity ?
-          std::numeric_limits<Value>::infinity() : MAX)
+          std::numeric_limits<Value>::infinity() :
+          std::numeric_limits<Value>::max())
     {
-      // Check the number types
+      // Check the value types
       LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
         "The flow type of NetworkSimplex must be signed");
@@ -656,6 +646,55 @@
         "The cost type of NetworkSimplex must be signed");
 
-      // Reset data structures
-      reset();
+      // Resize vectors
+      _node_num = countNodes(_graph);
+      _arc_num = countArcs(_graph);
+      int all_node_num = _node_num + 1;
+      int max_arc_num = _arc_num + 2 * _node_num;
+
+      _source.resize(max_arc_num);
+      _target.resize(max_arc_num);
+
+      _lower.resize(_arc_num);
+      _upper.resize(_arc_num);
+      _cap.resize(max_arc_num);
+      _cost.resize(max_arc_num);
+      _supply.resize(all_node_num);
+      _flow.resize(max_arc_num);
+      _pi.resize(all_node_num);
+
+      _parent.resize(all_node_num);
+      _pred.resize(all_node_num);
+      _forward.resize(all_node_num);
+      _thread.resize(all_node_num);
+      _rev_thread.resize(all_node_num);
+      _succ_num.resize(all_node_num);
+      _last_succ.resize(all_node_num);
+      _state.resize(max_arc_num);
+
+      // Copy the graph (store the arcs in a mixed order)
+      int i = 0;
+      for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
+        _node_id[n] = i;
+      }
+      int k = std::max(int(std::sqrt(double(_arc_num))), 10);
+      i = 0;
+      for (ArcIt a(_graph); a != INVALID; ++a) {
+        _arc_id[a] = i;
+        _source[i] = _node_id[_graph.source(a)];
+        _target[i] = _node_id[_graph.target(a)];
+        if ((i += k) >= _arc_num) i = (i % k) + 1;
+      }
+
+      // Initialize maps
+      for (int i = 0; i != _node_num; ++i) {
+        _supply[i] = 0;
+      }
+      for (int i = 0; i != _arc_num; ++i) {
+        _lower[i] = 0;
+        _upper[i] = INF;
+        _cost[i] = 1;
+      }
+      _have_lower = false;
+      _stype = GEQ;
     }
 
@@ -691,5 +730,5 @@
     /// If it is not used before calling \ref run(), the upper bounds
     /// will be set to \ref INF on all arcs (i.e. the flow value will be
-    /// unbounded from above).
+    /// unbounded from above on each arc).
     ///
     /// \param map An arc map storing the upper bounds.
@@ -730,4 +769,5 @@
     /// If neither this function nor \ref stSupply() is used before
     /// calling \ref run(), the supply of each node will be set to zero.
+    /// (It makes sense only if non-zero lower bounds are given.)
     ///
     /// \param map A node map storing the supply values.
@@ -736,6 +776,4 @@
     ///
     /// \return <tt>(*this)</tt>
-    ///
-    /// \sa supplyType()
     template<typename SupplyMap>
     NetworkSimplex& supplyMap(const SupplyMap& map) {
@@ -752,7 +790,8 @@
     /// If neither this function nor \ref supplyMap() is used before
     /// calling \ref run(), the supply of each node will be set to zero.
+    /// (It makes sense only if non-zero lower bounds are given.)
     ///
     /// Using this function has the same effect as using \ref supplyMap()
-    /// with a map in which \c k is assigned to \c s, \c -k is
+    /// with such a map in which \c k is assigned to \c s, \c -k is
     /// assigned to \c t and all other nodes have zero supply value.
     ///
@@ -778,5 +817,5 @@
     /// type will be used.
     ///
-    /// For more information, see \ref SupplyType.
+    /// For more information see \ref SupplyType.
     ///
     /// \return <tt>(*this)</tt>
@@ -806,13 +845,13 @@
     /// \endcode
     ///
-    /// This function can be called more than once. All the given parameters
-    /// are kept for the next call, unless \ref resetParams() or \ref reset()
-    /// is used, thus only the modified parameters have to be set again.
-    /// If the underlying digraph was also modified after the construction
-    /// of the class (or the last \ref reset() call), then the \ref reset()
-    /// function must be called.
+    /// This function can be called more than once. All the parameters
+    /// that have been given are kept for the next call, unless
+    /// \ref reset() is called, thus only the modified parameters
+    /// have to be set again. See \ref reset() for examples.
+    /// However the underlying digraph must not be modified after this
+    /// class have been constructed, since it copies and extends the graph.
     ///
     /// \param pivot_rule The pivot rule that will be used during the
-    /// algorithm. For more information, see \ref PivotRule.
+    /// algorithm. For more information see \ref PivotRule.
     ///
     /// \return \c INFEASIBLE if no feasible flow exists,
@@ -825,5 +864,4 @@
     ///
     /// \see ProblemType, PivotRule
-    /// \see resetParams(), reset()
     ProblemType run(PivotRule pivot_rule = BLOCK_SEARCH) {
       if (!init()) return INFEASIBLE;
@@ -837,10 +875,9 @@
     /// \ref costMap(), \ref supplyMap(), \ref stSupply(), \ref supplyType().
     ///
-    /// It is useful for multiple \ref run() calls. Basically, all the given
-    /// parameters are kept for the next \ref run() call, unless
-    /// \ref resetParams() or \ref reset() is used.
-    /// If the underlying digraph was also modified after the construction
-    /// of the class or the last \ref reset() call, then the \ref reset()
-    /// function must be used, otherwise \ref resetParams() is sufficient.
+    /// It is useful for multiple run() calls. If this function is not
+    /// used, all the parameters given before are kept for the next
+    /// \ref run() call.
+    /// However the underlying digraph must not be modified after this
+    /// class have been constructed, since it copies and extends the graph.
     ///
     /// For example,
@@ -852,12 +889,12 @@
     ///     .supplyMap(sup).run();
     ///
-    ///   // Run again with modified cost map (resetParams() is not called,
+    ///   // Run again with modified cost map (reset() is not called,
     ///   // so only the cost map have to be set again)
     ///   cost[e] += 100;
     ///   ns.costMap(cost).run();
     ///
-    ///   // Run again from scratch using resetParams()
+    ///   // Run again from scratch using reset()
     ///   // (the lower bounds will be set to zero on all arcs)
-    ///   ns.resetParams();
+    ///   ns.reset();
     ///   ns.upperMap(capacity).costMap(cost)
     ///     .supplyMap(sup).run();
@@ -865,7 +902,5 @@
     ///
     /// \return <tt>(*this)</tt>
-    ///
-    /// \see reset(), run()
-    NetworkSimplex& resetParams() {
+    NetworkSimplex& reset() {
       for (int i = 0; i != _node_num; ++i) {
         _supply[i] = 0;
@@ -878,81 +913,4 @@
       _have_lower = false;
       _stype = GEQ;
-      return *this;
-    }
-
-    /// \brief Reset the internal data structures and all the parameters
-    /// that have been given before.
-    ///
-    /// This function resets the internal data structures and all the
-    /// paramaters that have been given before using functions \ref lowerMap(),
-    /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply(),
-    /// \ref supplyType().
-    ///
-    /// It is useful for multiple \ref run() calls. Basically, all the given
-    /// parameters are kept for the next \ref run() call, unless
-    /// \ref resetParams() or \ref reset() is used.
-    /// If the underlying digraph was also modified after the construction
-    /// of the class or the last \ref reset() call, then the \ref reset()
-    /// function must be used, otherwise \ref resetParams() is sufficient.
-    ///
-    /// See \ref resetParams() for examples.
-    ///
-    /// \return <tt>(*this)</tt>
-    ///
-    /// \see resetParams(), run()
-    NetworkSimplex& reset() {
-      // Resize vectors
-      _node_num = countNodes(_graph);
-      _arc_num = countArcs(_graph);
-      int all_node_num = _node_num + 1;
-      int max_arc_num = _arc_num + 2 * _node_num;
-
-      _source.resize(max_arc_num);
-      _target.resize(max_arc_num);
-
-      _lower.resize(_arc_num);
-      _upper.resize(_arc_num);
-      _cap.resize(max_arc_num);
-      _cost.resize(max_arc_num);
-      _supply.resize(all_node_num);
-      _flow.resize(max_arc_num);
-      _pi.resize(all_node_num);
-
-      _parent.resize(all_node_num);
-      _pred.resize(all_node_num);
-      _pred_dir.resize(all_node_num);
-      _thread.resize(all_node_num);
-      _rev_thread.resize(all_node_num);
-      _succ_num.resize(all_node_num);
-      _last_succ.resize(all_node_num);
-      _state.resize(max_arc_num);
-
-      // Copy the graph
-      int i = 0;
-      for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
-        _node_id[n] = i;
-      }
-      if (_arc_mixing) {
-        // Store the arcs in a mixed order
-        const int skip = std::max(_arc_num / _node_num, 3);
-        int i = 0, j = 0;
-        for (ArcIt a(_graph); a != INVALID; ++a) {
-          _arc_id[a] = i;
-          _source[i] = _node_id[_graph.source(a)];
-          _target[i] = _node_id[_graph.target(a)];
-          if ((i += skip) >= _arc_num) i = ++j;
-        }
-      } else {
-        // Store the arcs in the original order
-        int i = 0;
-        for (ArcIt a(_graph); a != INVALID; ++a, ++i) {
-          _arc_id[a] = i;
-          _source[i] = _node_id[_graph.source(a)];
-          _target[i] = _node_id[_graph.target(a)];
-        }
-      }
-
-      // Reset parameters
-      resetParams();
       return *this;
     }
@@ -1067,7 +1025,7 @@
           Value c = _lower[i];
           if (c >= 0) {
-            _cap[i] = _upper[i] < MAX ? _upper[i] - c : INF;
+            _cap[i] = _upper[i] < INF ? _upper[i] - c : INF;
           } else {
-            _cap[i] = _upper[i] < MAX + c ? _upper[i] - c : INF;
+            _cap[i] = _upper[i] < INF + c ? _upper[i] - c : INF;
           }
           _supply[_source[i]] -= c;
@@ -1124,5 +1082,5 @@
           _state[e] = STATE_TREE;
           if (_supply[u] >= 0) {
-            _pred_dir[u] = DIR_UP;
+            _forward[u] = true;
             _pi[u] = 0;
             _source[e] = u;
@@ -1131,5 +1089,5 @@
             _cost[e] = 0;
           } else {
-            _pred_dir[u] = DIR_DOWN;
+            _forward[u] = false;
             _pi[u] = ART_COST;
             _source[e] = _root;
@@ -1151,5 +1109,5 @@
           _last_succ[u] = u;
           if (_supply[u] >= 0) {
-            _pred_dir[u] = DIR_UP;
+            _forward[u] = true;
             _pi[u] = 0;
             _pred[u] = e;
@@ -1161,5 +1119,5 @@
             _state[e] = STATE_TREE;
           } else {
-            _pred_dir[u] = DIR_DOWN;
+            _forward[u] = false;
             _pi[u] = ART_COST;
             _pred[u] = f;
@@ -1192,5 +1150,5 @@
           _last_succ[u] = u;
           if (_supply[u] <= 0) {
-            _pred_dir[u] = DIR_DOWN;
+            _forward[u] = false;
             _pi[u] = 0;
             _pred[u] = e;
@@ -1202,5 +1160,5 @@
             _state[e] = STATE_TREE;
           } else {
-            _pred_dir[u] = DIR_UP;
+            _forward[u] = true;
             _pi[u] = -ART_COST;
             _pred[u] = f;
@@ -1245,5 +1203,4 @@
       // Initialize first and second nodes according to the direction
       // of the cycle
-      int first, second;
       if (_state[in_arc] == STATE_LOWER) {
         first  = _source[in_arc];
@@ -1255,15 +1212,12 @@
       delta = _cap[in_arc];
       int result = 0;
-      Value c, d;
+      Value d;
       int e;
 
-      // Search the cycle form the first node to the join node
+      // Search the cycle along the path form the first node to the root
       for (int u = first; u != join; u = _parent[u]) {
         e = _pred[u];
-        d = _flow[e];
-        if (_pred_dir[u] == DIR_DOWN) {
-          c = _cap[e];
-          d = c >= MAX ? INF : c - d;
-        }
+        d = _forward[u] ?
+          _flow[e] : (_cap[e] == INF ? INF : _cap[e] - _flow[e]);
         if (d < delta) {
           delta = d;
@@ -1272,13 +1226,9 @@
         }
       }
-
-      // Search the cycle form the second node to the join node
+      // Search the cycle along the path form the second node to the root
       for (int u = second; u != join; u = _parent[u]) {
         e = _pred[u];
-        d = _flow[e];
-        if (_pred_dir[u] == DIR_UP) {
-          c = _cap[e];
-          d = c >= MAX ? INF : c - d;
-        }
+        d = _forward[u] ?
+          (_cap[e] == INF ? INF : _cap[e] - _flow[e]) : _flow[e];
         if (d <= delta) {
           delta = d;
@@ -1305,8 +1255,8 @@
         _flow[in_arc] += val;
         for (int u = _source[in_arc]; u != join; u = _parent[u]) {
-          _flow[_pred[u]] -= _pred_dir[u] * val;
+          _flow[_pred[u]] += _forward[u] ? -val : val;
         }
         for (int u = _target[in_arc]; u != join; u = _parent[u]) {
-          _flow[_pred[u]] += _pred_dir[u] * val;
+          _flow[_pred[u]] += _forward[u] ? val : -val;
         }
       }
@@ -1323,4 +1273,5 @@
     // Update the tree structure
     void updateTreeStructure() {
+      int u, w;
       int old_rev_thread = _rev_thread[u_out];
       int old_succ_num = _succ_num[u_out];
@@ -1328,225 +1279,126 @@
       v_out = _parent[u_out];
 
-      // Check if u_in and u_out coincide
-      if (u_in == u_out) {
-        // Update _parent, _pred, _pred_dir
-        _parent[u_in] = v_in;
-        _pred[u_in] = in_arc;
-        _pred_dir[u_in] = u_in == _source[in_arc] ? DIR_UP : DIR_DOWN;
-
-        // Update _thread and _rev_thread
-        if (_thread[v_in] != u_out) {
-          int after = _thread[old_last_succ];
-          _thread[old_rev_thread] = after;
-          _rev_thread[after] = old_rev_thread;
-          after = _thread[v_in];
-          _thread[v_in] = u_out;
-          _rev_thread[u_out] = v_in;
-          _thread[old_last_succ] = after;
-          _rev_thread[after] = old_last_succ;
-        }
+      u = _last_succ[u_in];  // the last successor of u_in
+      right = _thread[u];    // the node after it
+
+      // Handle the case when old_rev_thread equals to v_in
+      // (it also means that join and v_out coincide)
+      if (old_rev_thread == v_in) {
+        last = _thread[_last_succ[u_out]];
       } else {
-        // Handle the case when old_rev_thread equals to v_in
-        // (it also means that join and v_out coincide)
-        int thread_continue = old_rev_thread == v_in ?
-          _thread[old_last_succ] : _thread[v_in];
-
-        // Update _thread and _parent along the stem nodes (i.e. the nodes
-        // between u_in and u_out, whose parent have to be changed)
-        int stem = u_in;              // the current stem node
-        int par_stem = v_in;          // the new parent of stem
-        int next_stem;                // the next stem node
-        int last = _last_succ[u_in];  // the last successor of stem
-        int before, after = _thread[last];
-        _thread[v_in] = u_in;
-        _dirty_revs.clear();
-        _dirty_revs.push_back(v_in);
-        while (stem != u_out) {
-          // Insert the next stem node into the thread list
-          next_stem = _parent[stem];
-          _thread[last] = next_stem;
-          _dirty_revs.push_back(last);
-
-          // Remove the subtree of stem from the thread list
-          before = _rev_thread[stem];
-          _thread[before] = after;
-          _rev_thread[after] = before;
-
-          // Change the parent node and shift stem nodes
-          _parent[stem] = par_stem;
-          par_stem = stem;
-          stem = next_stem;
-
-          // Update last and after
-          last = _last_succ[stem] == _last_succ[par_stem] ?
-            _rev_thread[par_stem] : _last_succ[stem];
-          after = _thread[last];
-        }
-        _parent[u_out] = par_stem;
-        _thread[last] = thread_continue;
-        _rev_thread[thread_continue] = last;
-        _last_succ[u_out] = last;
-
-        // Remove the subtree of u_out from the thread list except for
-        // the case when old_rev_thread equals to v_in
-        if (old_rev_thread != v_in) {
-          _thread[old_rev_thread] = after;
-          _rev_thread[after] = old_rev_thread;
-        }
-
-        // Update _rev_thread using the new _thread values
-        for (int i = 0; i != int(_dirty_revs.size()); ++i) {
-          int u = _dirty_revs[i];
-          _rev_thread[_thread[u]] = u;
-        }
-
-        // Update _pred, _pred_dir, _last_succ and _succ_num for the
-        // stem nodes from u_out to u_in
-        int tmp_sc = 0, tmp_ls = _last_succ[u_out];
-        for (int u = u_out, p = _parent[u]; u != u_in; u = p, p = _parent[u]) {
-          _pred[u] = _pred[p];
-          _pred_dir[u] = -_pred_dir[p];
-          tmp_sc += _succ_num[u] - _succ_num[p];
-          _succ_num[u] = tmp_sc;
-          _last_succ[p] = tmp_ls;
-        }
-        _pred[u_in] = in_arc;
-        _pred_dir[u_in] = u_in == _source[in_arc] ? DIR_UP : DIR_DOWN;
-        _succ_num[u_in] = old_succ_num;
+        last = _thread[v_in];
+      }
+
+      // Update _thread and _parent along the stem nodes (i.e. the nodes
+      // between u_in and u_out, whose parent have to be changed)
+      _thread[v_in] = stem = u_in;
+      _dirty_revs.clear();
+      _dirty_revs.push_back(v_in);
+      par_stem = v_in;
+      while (stem != u_out) {
+        // Insert the next stem node into the thread list
+        new_stem = _parent[stem];
+        _thread[u] = new_stem;
+        _dirty_revs.push_back(u);
+
+        // Remove the subtree of stem from the thread list
+        w = _rev_thread[stem];
+        _thread[w] = right;
+        _rev_thread[right] = w;
+
+        // Change the parent node and shift stem nodes
+        _parent[stem] = par_stem;
+        par_stem = stem;
+        stem = new_stem;
+
+        // Update u and right
+        u = _last_succ[stem] == _last_succ[par_stem] ?
+          _rev_thread[par_stem] : _last_succ[stem];
+        right = _thread[u];
+      }
+      _parent[u_out] = par_stem;
+      _thread[u] = last;
+      _rev_thread[last] = u;
+      _last_succ[u_out] = u;
+
+      // Remove the subtree of u_out from the thread list except for
+      // the case when old_rev_thread equals to v_in
+      // (it also means that join and v_out coincide)
+      if (old_rev_thread != v_in) {
+        _thread[old_rev_thread] = right;
+        _rev_thread[right] = old_rev_thread;
+      }
+
+      // Update _rev_thread using the new _thread values
+      for (int i = 0; i < int(_dirty_revs.size()); ++i) {
+        u = _dirty_revs[i];
+        _rev_thread[_thread[u]] = u;
+      }
+
+      // Update _pred, _forward, _last_succ and _succ_num for the
+      // stem nodes from u_out to u_in
+      int tmp_sc = 0, tmp_ls = _last_succ[u_out];
+      u = u_out;
+      while (u != u_in) {
+        w = _parent[u];
+        _pred[u] = _pred[w];
+        _forward[u] = !_forward[w];
+        tmp_sc += _succ_num[u] - _succ_num[w];
+        _succ_num[u] = tmp_sc;
+        _last_succ[w] = tmp_ls;
+        u = w;
+      }
+      _pred[u_in] = in_arc;
+      _forward[u_in] = (u_in == _source[in_arc]);
+      _succ_num[u_in] = old_succ_num;
+
+      // Set limits for updating _last_succ form v_in and v_out
+      // towards the root
+      int up_limit_in = -1;
+      int up_limit_out = -1;
+      if (_last_succ[join] == v_in) {
+        up_limit_out = join;
+      } else {
+        up_limit_in = join;
       }
 
       // Update _last_succ from v_in towards the root
-      int up_limit_out = _last_succ[join] == v_in ? join : -1;
-      int last_succ_out = _last_succ[u_out];
-      for (int u = v_in; u != -1 && _last_succ[u] == v_in; u = _parent[u]) {
-        _last_succ[u] = last_succ_out;
-      }
-
+      for (u = v_in; u != up_limit_in && _last_succ[u] == v_in;
+           u = _parent[u]) {
+        _last_succ[u] = _last_succ[u_out];
+      }
       // Update _last_succ from v_out towards the root
       if (join != old_rev_thread && v_in != old_rev_thread) {
-        for (int u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
+        for (u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
              u = _parent[u]) {
           _last_succ[u] = old_rev_thread;
         }
-      }
-      else if (last_succ_out != old_last_succ) {
-        for (int u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
+      } else {
+        for (u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
              u = _parent[u]) {
-          _last_succ[u] = last_succ_out;
+          _last_succ[u] = _last_succ[u_out];
         }
       }
 
       // Update _succ_num from v_in to join
-      for (int u = v_in; u != join; u = _parent[u]) {
+      for (u = v_in; u != join; u = _parent[u]) {
         _succ_num[u] += old_succ_num;
       }
       // Update _succ_num from v_out to join
-      for (int u = v_out; u != join; u = _parent[u]) {
+      for (u = v_out; u != join; u = _parent[u]) {
         _succ_num[u] -= old_succ_num;
       }
     }
 
-    // Update potentials in the subtree that has been moved
+    // Update potentials
     void updatePotential() {
-      Cost sigma = _pi[v_in] - _pi[u_in] -
-                   _pred_dir[u_in] * _cost[in_arc];
+      Cost sigma = _forward[u_in] ?
+        _pi[v_in] - _pi[u_in] - _cost[_pred[u_in]] :
+        _pi[v_in] - _pi[u_in] + _cost[_pred[u_in]];
+      // Update potentials in the subtree, which has been moved
       int end = _thread[_last_succ[u_in]];
       for (int u = u_in; u != end; u = _thread[u]) {
         _pi[u] += sigma;
       }
-    }
-
-    // Heuristic initial pivots
-    bool initialPivots() {
-      Value curr, total = 0;
-      std::vector<Node> supply_nodes, demand_nodes;
-      for (NodeIt u(_graph); u != INVALID; ++u) {
-        curr = _supply[_node_id[u]];
-        if (curr > 0) {
-          total += curr;
-          supply_nodes.push_back(u);
-        }
-        else if (curr < 0) {
-          demand_nodes.push_back(u);
-        }
-      }
-      if (_sum_supply > 0) total -= _sum_supply;
-      if (total <= 0) return true;
-
-      IntVector arc_vector;
-      if (_sum_supply >= 0) {
-        if (supply_nodes.size() == 1 && demand_nodes.size() == 1) {
-          // Perform a reverse graph search from the sink to the source
-          typename GR::template NodeMap<bool> reached(_graph, false);
-          Node s = supply_nodes[0], t = demand_nodes[0];
-          std::vector<Node> stack;
-          reached[t] = true;
-          stack.push_back(t);
-          while (!stack.empty()) {
-            Node u, v = stack.back();
-            stack.pop_back();
-            if (v == s) break;
-            for (InArcIt a(_graph, v); a != INVALID; ++a) {
-              if (reached[u = _graph.source(a)]) continue;
-              int j = _arc_id[a];
-              if (_cap[j] >= total) {
-                arc_vector.push_back(j);
-                reached[u] = true;
-                stack.push_back(u);
-              }
-            }
-          }
-        } else {
-          // Find the min. cost incomming arc for each demand node
-          for (int i = 0; i != int(demand_nodes.size()); ++i) {
-            Node v = demand_nodes[i];
-            Cost c, min_cost = std::numeric_limits<Cost>::max();
-            Arc min_arc = INVALID;
-            for (InArcIt a(_graph, v); a != INVALID; ++a) {
-              c = _cost[_arc_id[a]];
-              if (c < min_cost) {
-                min_cost = c;
-                min_arc = a;
-              }
-            }
-            if (min_arc != INVALID) {
-              arc_vector.push_back(_arc_id[min_arc]);
-            }
-          }
-        }
-      } else {
-        // Find the min. cost outgoing arc for each supply node
-        for (int i = 0; i != int(supply_nodes.size()); ++i) {
-          Node u = supply_nodes[i];
-          Cost c, min_cost = std::numeric_limits<Cost>::max();
-          Arc min_arc = INVALID;
-          for (OutArcIt a(_graph, u); a != INVALID; ++a) {
-            c = _cost[_arc_id[a]];
-            if (c < min_cost) {
-              min_cost = c;
-              min_arc = a;
-            }
-          }
-          if (min_arc != INVALID) {
-            arc_vector.push_back(_arc_id[min_arc]);
-          }
-        }
-      }
-
-      // Perform heuristic initial pivots
-      for (int i = 0; i != int(arc_vector.size()); ++i) {
-        in_arc = arc_vector[i];
-        if (_state[in_arc] * (_cost[in_arc] + _pi[_source[in_arc]] -
-            _pi[_target[in_arc]]) >= 0) continue;
-        findJoinNode();
-        bool change = findLeavingArc();
-        if (delta >= MAX) return false;
-        changeFlow(change);
-        if (change) {
-          updateTreeStructure();
-          updatePotential();
-        }
-      }
-      return true;
     }
 
@@ -1573,12 +1425,9 @@
       PivotRuleImpl pivot(*this);
 
-      // Perform heuristic initial pivots
-      if (!initialPivots()) return UNBOUNDED;
-
       // Execute the Network Simplex algorithm
       while (pivot.findEnteringArc()) {
         findJoinNode();
         bool change = findLeavingArc();
-        if (delta >= MAX) return UNBOUNDED;
+        if (delta >= INF) return UNBOUNDED;
         changeFlow(change);
         if (change) {
