Merge
authorAlpar Juttner <alpar@cs.elte.hu>
Tue, 21 Apr 2009 13:08:19 +0100
changeset 6470ba8dfce7259
parent 646 f63e87b9748e
parent 642 16d7255a6849
child 658 85cb3aa71cce
Merge
lemon/max_matching.h
test/max_matching_test.cc
     1.1 --- a/doc/groups.dox	Tue Apr 21 10:34:49 2009 +0100
     1.2 +++ b/doc/groups.dox	Tue Apr 21 13:08:19 2009 +0100
     1.3 @@ -435,9 +435,10 @@
     1.4  @ingroup algs
     1.5  \brief Algorithms for finding matchings in graphs and bipartite graphs.
     1.6  
     1.7 -This group contains algorithm objects and functions to calculate
     1.8 +This group contains the algorithms for calculating
     1.9  matchings in graphs and bipartite graphs. The general matching problem is
    1.10 -finding a subset of the arcs which does not shares common endpoints.
    1.11 +finding a subset of the edges for which each node has at most one incident
    1.12 +edge.
    1.13  
    1.14  There are several different algorithms for calculate matchings in
    1.15  graphs.  The matching problems in bipartite graphs are generally
     2.1 --- a/lemon/Makefile.am	Tue Apr 21 10:34:49 2009 +0100
     2.2 +++ b/lemon/Makefile.am	Tue Apr 21 13:08:19 2009 +0100
     2.3 @@ -89,8 +89,8 @@
     2.4  	lemon/lp_skeleton.h \
     2.5  	lemon/list_graph.h \
     2.6  	lemon/maps.h \
     2.7 +	lemon/matching.h \
     2.8  	lemon/math.h \
     2.9 -	lemon/max_matching.h \
    2.10  	lemon/min_cost_arborescence.h \
    2.11  	lemon/nauty_reader.h \
    2.12  	lemon/path.h \
     3.1 --- a/lemon/euler.h	Tue Apr 21 10:34:49 2009 +0100
     3.2 +++ b/lemon/euler.h	Tue Apr 21 13:08:19 2009 +0100
     3.3 @@ -26,33 +26,31 @@
     3.4  
     3.5  /// \ingroup graph_properties
     3.6  /// \file
     3.7 -/// \brief Euler tour
     3.8 +/// \brief Euler tour iterators and a function for checking the \e Eulerian 
     3.9 +/// property.
    3.10  ///
    3.11 -///This file provides an Euler tour iterator and ways to check
    3.12 -///if a digraph is euler.
    3.13 -
    3.14 +///This file provides Euler tour iterators and a function to check
    3.15 +///if a (di)graph is \e Eulerian.
    3.16  
    3.17  namespace lemon {
    3.18  
    3.19 -  ///Euler iterator for digraphs.
    3.20 +  ///Euler tour iterator for digraphs.
    3.21  
    3.22 -  /// \ingroup graph_properties
    3.23 -  ///This iterator converts to the \c Arc type of the digraph and using
    3.24 -  ///operator ++, it provides an Euler tour of a \e directed
    3.25 -  ///graph (if there exists).
    3.26 +  /// \ingroup graph_prop
    3.27 +  ///This iterator provides an Euler tour (Eulerian circuit) of a \e directed
    3.28 +  ///graph (if there exists) and it converts to the \c Arc type of the digraph.
    3.29    ///
    3.30 -  ///For example
    3.31 -  ///if the given digraph is Euler (i.e it has only one nontrivial component
    3.32 -  ///and the in-degree is equal to the out-degree for all nodes),
    3.33 -  ///the following code will put the arcs of \c g
    3.34 -  ///to the vector \c et according to an
    3.35 -  ///Euler tour of \c g.
    3.36 +  ///For example, if the given digraph has an Euler tour (i.e it has only one
    3.37 +  ///non-trivial component and the in-degree is equal to the out-degree 
    3.38 +  ///for all nodes), then the following code will put the arcs of \c g
    3.39 +  ///to the vector \c et according to an Euler tour of \c g.
    3.40    ///\code
    3.41    ///  std::vector<ListDigraph::Arc> et;
    3.42 -  ///  for(DiEulerIt<ListDigraph> e(g),e!=INVALID;++e)
    3.43 +  ///  for(DiEulerIt<ListDigraph> e(g); e!=INVALID; ++e)
    3.44    ///    et.push_back(e);
    3.45    ///\endcode
    3.46 -  ///If \c g is not Euler then the resulted tour will not be full or closed.
    3.47 +  ///If \c g has no Euler tour, then the resulted walk will not be closed
    3.48 +  ///or not contain all arcs.
    3.49    ///\sa EulerIt
    3.50    template<typename GR>
    3.51    class DiEulerIt
    3.52 @@ -65,53 +63,65 @@
    3.53      typedef typename GR::InArcIt InArcIt;
    3.54  
    3.55      const GR &g;
    3.56 -    typename GR::template NodeMap<OutArcIt> nedge;
    3.57 +    typename GR::template NodeMap<OutArcIt> narc;
    3.58      std::list<Arc> euler;
    3.59  
    3.60    public:
    3.61  
    3.62      ///Constructor
    3.63  
    3.64 +    ///Constructor.
    3.65      ///\param gr A digraph.
    3.66 -    ///\param start The starting point of the tour. If it is not given
    3.67 -    ///       the tour will start from the first node.
    3.68 +    ///\param start The starting point of the tour. If it is not given,
    3.69 +    ///the tour will start from the first node that has an outgoing arc.
    3.70      DiEulerIt(const GR &gr, typename GR::Node start = INVALID)
    3.71 -      : g(gr), nedge(g)
    3.72 +      : g(gr), narc(g)
    3.73      {
    3.74 -      if(start==INVALID) start=NodeIt(g);
    3.75 -      for(NodeIt n(g);n!=INVALID;++n) nedge[n]=OutArcIt(g,n);
    3.76 -      while(nedge[start]!=INVALID) {
    3.77 -        euler.push_back(nedge[start]);
    3.78 -        Node next=g.target(nedge[start]);
    3.79 -        ++nedge[start];
    3.80 -        start=next;
    3.81 +      if (start==INVALID) {
    3.82 +        NodeIt n(g);
    3.83 +        while (n!=INVALID && OutArcIt(g,n)==INVALID) ++n;
    3.84 +        start=n;
    3.85 +      }
    3.86 +      if (start!=INVALID) {
    3.87 +        for (NodeIt n(g); n!=INVALID; ++n) narc[n]=OutArcIt(g,n);
    3.88 +        while (narc[start]!=INVALID) {
    3.89 +          euler.push_back(narc[start]);
    3.90 +          Node next=g.target(narc[start]);
    3.91 +          ++narc[start];
    3.92 +          start=next;
    3.93 +        }
    3.94        }
    3.95      }
    3.96  
    3.97 -    ///Arc Conversion
    3.98 +    ///Arc conversion
    3.99      operator Arc() { return euler.empty()?INVALID:euler.front(); }
   3.100 +    ///Compare with \c INVALID
   3.101      bool operator==(Invalid) { return euler.empty(); }
   3.102 +    ///Compare with \c INVALID
   3.103      bool operator!=(Invalid) { return !euler.empty(); }
   3.104  
   3.105      ///Next arc of the tour
   3.106 +
   3.107 +    ///Next arc of the tour
   3.108 +    ///
   3.109      DiEulerIt &operator++() {
   3.110        Node s=g.target(euler.front());
   3.111        euler.pop_front();
   3.112 -      //This produces a warning.Strange.
   3.113 -      //std::list<Arc>::iterator next=euler.begin();
   3.114        typename std::list<Arc>::iterator next=euler.begin();
   3.115 -      while(nedge[s]!=INVALID) {
   3.116 -        euler.insert(next,nedge[s]);
   3.117 -        Node n=g.target(nedge[s]);
   3.118 -        ++nedge[s];
   3.119 +      while(narc[s]!=INVALID) {
   3.120 +        euler.insert(next,narc[s]);
   3.121 +        Node n=g.target(narc[s]);
   3.122 +        ++narc[s];
   3.123          s=n;
   3.124        }
   3.125        return *this;
   3.126      }
   3.127      ///Postfix incrementation
   3.128  
   3.129 +    /// Postfix incrementation.
   3.130 +    ///
   3.131      ///\warning This incrementation
   3.132 -    ///returns an \c Arc, not an \ref DiEulerIt, as one may
   3.133 +    ///returns an \c Arc, not a \ref DiEulerIt, as one may
   3.134      ///expect.
   3.135      Arc operator++(int)
   3.136      {
   3.137 @@ -121,30 +131,28 @@
   3.138      }
   3.139    };
   3.140  
   3.141 -  ///Euler iterator for graphs.
   3.142 +  ///Euler tour iterator for graphs.
   3.143  
   3.144    /// \ingroup graph_properties
   3.145 -  ///This iterator converts to the \c Arc (or \c Edge)
   3.146 -  ///type of the digraph and using
   3.147 -  ///operator ++, it provides an Euler tour of an undirected
   3.148 -  ///digraph (if there exists).
   3.149 +  ///This iterator provides an Euler tour (Eulerian circuit) of an
   3.150 +  ///\e undirected graph (if there exists) and it converts to the \c Arc
   3.151 +  ///and \c Edge types of the graph.
   3.152    ///
   3.153 -  ///For example
   3.154 -  ///if the given digraph if Euler (i.e it has only one nontrivial component
   3.155 -  ///and the degree of each node is even),
   3.156 +  ///For example, if the given graph has an Euler tour (i.e it has only one 
   3.157 +  ///non-trivial component and the degree of each node is even),
   3.158    ///the following code will print the arc IDs according to an
   3.159    ///Euler tour of \c g.
   3.160    ///\code
   3.161 -  ///  for(EulerIt<ListGraph> e(g),e!=INVALID;++e) {
   3.162 +  ///  for(EulerIt<ListGraph> e(g); e!=INVALID; ++e) {
   3.163    ///    std::cout << g.id(Edge(e)) << std::eol;
   3.164    ///  }
   3.165    ///\endcode
   3.166 -  ///Although the iterator provides an Euler tour of an graph,
   3.167 -  ///it still returns Arcs in order to indicate the direction of the tour.
   3.168 -  ///(But Arc will convert to Edges, of course).
   3.169 +  ///Although this iterator is for undirected graphs, it still returns 
   3.170 +  ///arcs in order to indicate the direction of the tour.
   3.171 +  ///(But arcs convert to edges, of course.)
   3.172    ///
   3.173 -  ///If \c g is not Euler then the resulted tour will not be full or closed.
   3.174 -  ///\sa EulerIt
   3.175 +  ///If \c g has no Euler tour, then the resulted walk will not be closed
   3.176 +  ///or not contain all edges.
   3.177    template<typename GR>
   3.178    class EulerIt
   3.179    {
   3.180 @@ -157,7 +165,7 @@
   3.181      typedef typename GR::InArcIt InArcIt;
   3.182  
   3.183      const GR &g;
   3.184 -    typename GR::template NodeMap<OutArcIt> nedge;
   3.185 +    typename GR::template NodeMap<OutArcIt> narc;
   3.186      typename GR::template EdgeMap<bool> visited;
   3.187      std::list<Arc> euler;
   3.188  
   3.189 @@ -165,47 +173,56 @@
   3.190  
   3.191      ///Constructor
   3.192  
   3.193 -    ///\param gr An graph.
   3.194 -    ///\param start The starting point of the tour. If it is not given
   3.195 -    ///       the tour will start from the first node.
   3.196 +    ///Constructor.
   3.197 +    ///\param gr A graph.
   3.198 +    ///\param start The starting point of the tour. If it is not given,
   3.199 +    ///the tour will start from the first node that has an incident edge.
   3.200      EulerIt(const GR &gr, typename GR::Node start = INVALID)
   3.201 -      : g(gr), nedge(g), visited(g, false)
   3.202 +      : g(gr), narc(g), visited(g, false)
   3.203      {
   3.204 -      if(start==INVALID) start=NodeIt(g);
   3.205 -      for(NodeIt n(g);n!=INVALID;++n) nedge[n]=OutArcIt(g,n);
   3.206 -      while(nedge[start]!=INVALID) {
   3.207 -        euler.push_back(nedge[start]);
   3.208 -        visited[nedge[start]]=true;
   3.209 -        Node next=g.target(nedge[start]);
   3.210 -        ++nedge[start];
   3.211 -        start=next;
   3.212 -        while(nedge[start]!=INVALID && visited[nedge[start]]) ++nedge[start];
   3.213 +      if (start==INVALID) {
   3.214 +        NodeIt n(g);
   3.215 +        while (n!=INVALID && OutArcIt(g,n)==INVALID) ++n;
   3.216 +        start=n;
   3.217 +      }
   3.218 +      if (start!=INVALID) {
   3.219 +        for (NodeIt n(g); n!=INVALID; ++n) narc[n]=OutArcIt(g,n);
   3.220 +        while(narc[start]!=INVALID) {
   3.221 +          euler.push_back(narc[start]);
   3.222 +          visited[narc[start]]=true;
   3.223 +          Node next=g.target(narc[start]);
   3.224 +          ++narc[start];
   3.225 +          start=next;
   3.226 +          while(narc[start]!=INVALID && visited[narc[start]]) ++narc[start];
   3.227 +        }
   3.228        }
   3.229      }
   3.230  
   3.231 -    ///Arc Conversion
   3.232 +    ///Arc conversion
   3.233      operator Arc() const { return euler.empty()?INVALID:euler.front(); }
   3.234 -    ///Arc Conversion
   3.235 +    ///Edge conversion
   3.236      operator Edge() const { return euler.empty()?INVALID:euler.front(); }
   3.237 -    ///\e
   3.238 +    ///Compare with \c INVALID
   3.239      bool operator==(Invalid) const { return euler.empty(); }
   3.240 -    ///\e
   3.241 +    ///Compare with \c INVALID
   3.242      bool operator!=(Invalid) const { return !euler.empty(); }
   3.243  
   3.244      ///Next arc of the tour
   3.245 +
   3.246 +    ///Next arc of the tour
   3.247 +    ///
   3.248      EulerIt &operator++() {
   3.249        Node s=g.target(euler.front());
   3.250        euler.pop_front();
   3.251        typename std::list<Arc>::iterator next=euler.begin();
   3.252 -
   3.253 -      while(nedge[s]!=INVALID) {
   3.254 -        while(nedge[s]!=INVALID && visited[nedge[s]]) ++nedge[s];
   3.255 -        if(nedge[s]==INVALID) break;
   3.256 +      while(narc[s]!=INVALID) {
   3.257 +        while(narc[s]!=INVALID && visited[narc[s]]) ++narc[s];
   3.258 +        if(narc[s]==INVALID) break;
   3.259          else {
   3.260 -          euler.insert(next,nedge[s]);
   3.261 -          visited[nedge[s]]=true;
   3.262 -          Node n=g.target(nedge[s]);
   3.263 -          ++nedge[s];
   3.264 +          euler.insert(next,narc[s]);
   3.265 +          visited[narc[s]]=true;
   3.266 +          Node n=g.target(narc[s]);
   3.267 +          ++narc[s];
   3.268            s=n;
   3.269          }
   3.270        }
   3.271 @@ -214,9 +231,10 @@
   3.272  
   3.273      ///Postfix incrementation
   3.274  
   3.275 -    ///\warning This incrementation
   3.276 -    ///returns an \c Arc, not an \ref EulerIt, as one may
   3.277 -    ///expect.
   3.278 +    /// Postfix incrementation.
   3.279 +    ///
   3.280 +    ///\warning This incrementation returns an \c Arc (which converts to 
   3.281 +    ///an \c Edge), not an \ref EulerIt, as one may expect.
   3.282      Arc operator++(int)
   3.283      {
   3.284        Arc e=*this;
   3.285 @@ -226,18 +244,23 @@
   3.286    };
   3.287  
   3.288  
   3.289 -  ///Checks if the graph is Eulerian
   3.290 +  ///Check if the given graph is \e Eulerian
   3.291  
   3.292    /// \ingroup graph_properties
   3.293 -  ///Checks if the graph is Eulerian. It works for both directed and undirected
   3.294 -  ///graphs.
   3.295 -  ///\note By definition, a digraph is called \e Eulerian if
   3.296 -  ///and only if it is connected and the number of its incoming and outgoing
   3.297 +  ///This function checks if the given graph is \e Eulerian.
   3.298 +  ///It works for both directed and undirected graphs.
   3.299 +  ///
   3.300 +  ///By definition, a digraph is called \e Eulerian if
   3.301 +  ///and only if it is connected and the number of incoming and outgoing
   3.302    ///arcs are the same for each node.
   3.303    ///Similarly, an undirected graph is called \e Eulerian if
   3.304 -  ///and only if it is connected and the number of incident arcs is even
   3.305 -  ///for each node. <em>Therefore, there are digraphs which are not Eulerian,
   3.306 -  ///but still have an Euler tour</em>.
   3.307 +  ///and only if it is connected and the number of incident edges is even
   3.308 +  ///for each node.
   3.309 +  ///
   3.310 +  ///\note There are (di)graphs that are not Eulerian, but still have an
   3.311 +  /// Euler tour, since they may contain isolated nodes.
   3.312 +  ///
   3.313 +  ///\sa DiEulerIt, EulerIt
   3.314    template<typename GR>
   3.315  #ifdef DOXYGEN
   3.316    bool
   3.317 @@ -256,7 +279,7 @@
   3.318    {
   3.319      for(typename GR::NodeIt n(g);n!=INVALID;++n)
   3.320        if(countInArcs(g,n)!=countOutArcs(g,n)) return false;
   3.321 -    return connected(Undirector<const GR>(g));
   3.322 +    return connected(undirector(g));
   3.323    }
   3.324  
   3.325  }
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/lemon/matching.h	Tue Apr 21 13:08:19 2009 +0100
     4.3 @@ -0,0 +1,3244 @@
     4.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
     4.5 + *
     4.6 + * This file is a part of LEMON, a generic C++ optimization library.
     4.7 + *
     4.8 + * Copyright (C) 2003-2009
     4.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
    4.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
    4.11 + *
    4.12 + * Permission to use, modify and distribute this software is granted
    4.13 + * provided that this copyright notice appears in all copies. For
    4.14 + * precise terms see the accompanying LICENSE file.
    4.15 + *
    4.16 + * This software is provided "AS IS" with no warranty of any kind,
    4.17 + * express or implied, and with no claim as to its suitability for any
    4.18 + * purpose.
    4.19 + *
    4.20 + */
    4.21 +
    4.22 +#ifndef LEMON_MAX_MATCHING_H
    4.23 +#define LEMON_MAX_MATCHING_H
    4.24 +
    4.25 +#include <vector>
    4.26 +#include <queue>
    4.27 +#include <set>
    4.28 +#include <limits>
    4.29 +
    4.30 +#include <lemon/core.h>
    4.31 +#include <lemon/unionfind.h>
    4.32 +#include <lemon/bin_heap.h>
    4.33 +#include <lemon/maps.h>
    4.34 +
    4.35 +///\ingroup matching
    4.36 +///\file
    4.37 +///\brief Maximum matching algorithms in general graphs.
    4.38 +
    4.39 +namespace lemon {
    4.40 +
    4.41 +  /// \ingroup matching
    4.42 +  ///
    4.43 +  /// \brief Maximum cardinality matching in general graphs
    4.44 +  ///
    4.45 +  /// This class implements Edmonds' alternating forest matching algorithm
    4.46 +  /// for finding a maximum cardinality matching in a general undirected graph.
    4.47 +  /// It can be started from an arbitrary initial matching 
    4.48 +  /// (the default is the empty one).
    4.49 +  ///
    4.50 +  /// The dual solution of the problem is a map of the nodes to
    4.51 +  /// \ref MaxMatching::Status "Status", having values \c EVEN (or \c D),
    4.52 +  /// \c ODD (or \c A) and \c MATCHED (or \c C) defining the Gallai-Edmonds
    4.53 +  /// decomposition of the graph. The nodes in \c EVEN/D induce a subgraph
    4.54 +  /// with factor-critical components, the nodes in \c ODD/A form the
    4.55 +  /// canonical barrier, and the nodes in \c MATCHED/C induce a graph having
    4.56 +  /// a perfect matching. The number of the factor-critical components
    4.57 +  /// minus the number of barrier nodes is a lower bound on the
    4.58 +  /// unmatched nodes, and the matching is optimal if and only if this bound is
    4.59 +  /// tight. This decomposition can be obtained using \ref status() or
    4.60 +  /// \ref statusMap() after running the algorithm.
    4.61 +  ///
    4.62 +  /// \tparam GR The undirected graph type the algorithm runs on.
    4.63 +  template <typename GR>
    4.64 +  class MaxMatching {
    4.65 +  public:
    4.66 +
    4.67 +    /// The graph type of the algorithm
    4.68 +    typedef GR Graph;
    4.69 +    /// The type of the matching map
    4.70 +    typedef typename Graph::template NodeMap<typename Graph::Arc>
    4.71 +    MatchingMap;
    4.72 +
    4.73 +    ///\brief Status constants for Gallai-Edmonds decomposition.
    4.74 +    ///
    4.75 +    ///These constants are used for indicating the Gallai-Edmonds 
    4.76 +    ///decomposition of a graph. The nodes with status \c EVEN (or \c D)
    4.77 +    ///induce a subgraph with factor-critical components, the nodes with
    4.78 +    ///status \c ODD (or \c A) form the canonical barrier, and the nodes
    4.79 +    ///with status \c MATCHED (or \c C) induce a subgraph having a 
    4.80 +    ///perfect matching.
    4.81 +    enum Status {
    4.82 +      EVEN = 1,       ///< = 1. (\c D is an alias for \c EVEN.)
    4.83 +      D = 1,
    4.84 +      MATCHED = 0,    ///< = 0. (\c C is an alias for \c MATCHED.)
    4.85 +      C = 0,
    4.86 +      ODD = -1,       ///< = -1. (\c A is an alias for \c ODD.)
    4.87 +      A = -1,
    4.88 +      UNMATCHED = -2  ///< = -2.
    4.89 +    };
    4.90 +
    4.91 +    /// The type of the status map
    4.92 +    typedef typename Graph::template NodeMap<Status> StatusMap;
    4.93 +
    4.94 +  private:
    4.95 +
    4.96 +    TEMPLATE_GRAPH_TYPEDEFS(Graph);
    4.97 +
    4.98 +    typedef UnionFindEnum<IntNodeMap> BlossomSet;
    4.99 +    typedef ExtendFindEnum<IntNodeMap> TreeSet;
   4.100 +    typedef RangeMap<Node> NodeIntMap;
   4.101 +    typedef MatchingMap EarMap;
   4.102 +    typedef std::vector<Node> NodeQueue;
   4.103 +
   4.104 +    const Graph& _graph;
   4.105 +    MatchingMap* _matching;
   4.106 +    StatusMap* _status;
   4.107 +
   4.108 +    EarMap* _ear;
   4.109 +
   4.110 +    IntNodeMap* _blossom_set_index;
   4.111 +    BlossomSet* _blossom_set;
   4.112 +    NodeIntMap* _blossom_rep;
   4.113 +
   4.114 +    IntNodeMap* _tree_set_index;
   4.115 +    TreeSet* _tree_set;
   4.116 +
   4.117 +    NodeQueue _node_queue;
   4.118 +    int _process, _postpone, _last;
   4.119 +
   4.120 +    int _node_num;
   4.121 +
   4.122 +  private:
   4.123 +
   4.124 +    void createStructures() {
   4.125 +      _node_num = countNodes(_graph);
   4.126 +      if (!_matching) {
   4.127 +        _matching = new MatchingMap(_graph);
   4.128 +      }
   4.129 +      if (!_status) {
   4.130 +        _status = new StatusMap(_graph);
   4.131 +      }
   4.132 +      if (!_ear) {
   4.133 +        _ear = new EarMap(_graph);
   4.134 +      }
   4.135 +      if (!_blossom_set) {
   4.136 +        _blossom_set_index = new IntNodeMap(_graph);
   4.137 +        _blossom_set = new BlossomSet(*_blossom_set_index);
   4.138 +      }
   4.139 +      if (!_blossom_rep) {
   4.140 +        _blossom_rep = new NodeIntMap(_node_num);
   4.141 +      }
   4.142 +      if (!_tree_set) {
   4.143 +        _tree_set_index = new IntNodeMap(_graph);
   4.144 +        _tree_set = new TreeSet(*_tree_set_index);
   4.145 +      }
   4.146 +      _node_queue.resize(_node_num);
   4.147 +    }
   4.148 +
   4.149 +    void destroyStructures() {
   4.150 +      if (_matching) {
   4.151 +        delete _matching;
   4.152 +      }
   4.153 +      if (_status) {
   4.154 +        delete _status;
   4.155 +      }
   4.156 +      if (_ear) {
   4.157 +        delete _ear;
   4.158 +      }
   4.159 +      if (_blossom_set) {
   4.160 +        delete _blossom_set;
   4.161 +        delete _blossom_set_index;
   4.162 +      }
   4.163 +      if (_blossom_rep) {
   4.164 +        delete _blossom_rep;
   4.165 +      }
   4.166 +      if (_tree_set) {
   4.167 +        delete _tree_set_index;
   4.168 +        delete _tree_set;
   4.169 +      }
   4.170 +    }
   4.171 +
   4.172 +    void processDense(const Node& n) {
   4.173 +      _process = _postpone = _last = 0;
   4.174 +      _node_queue[_last++] = n;
   4.175 +
   4.176 +      while (_process != _last) {
   4.177 +        Node u = _node_queue[_process++];
   4.178 +        for (OutArcIt a(_graph, u); a != INVALID; ++a) {
   4.179 +          Node v = _graph.target(a);
   4.180 +          if ((*_status)[v] == MATCHED) {
   4.181 +            extendOnArc(a);
   4.182 +          } else if ((*_status)[v] == UNMATCHED) {
   4.183 +            augmentOnArc(a);
   4.184 +            return;
   4.185 +          }
   4.186 +        }
   4.187 +      }
   4.188 +
   4.189 +      while (_postpone != _last) {
   4.190 +        Node u = _node_queue[_postpone++];
   4.191 +
   4.192 +        for (OutArcIt a(_graph, u); a != INVALID ; ++a) {
   4.193 +          Node v = _graph.target(a);
   4.194 +
   4.195 +          if ((*_status)[v] == EVEN) {
   4.196 +            if (_blossom_set->find(u) != _blossom_set->find(v)) {
   4.197 +              shrinkOnEdge(a);
   4.198 +            }
   4.199 +          }
   4.200 +
   4.201 +          while (_process != _last) {
   4.202 +            Node w = _node_queue[_process++];
   4.203 +            for (OutArcIt b(_graph, w); b != INVALID; ++b) {
   4.204 +              Node x = _graph.target(b);
   4.205 +              if ((*_status)[x] == MATCHED) {
   4.206 +                extendOnArc(b);
   4.207 +              } else if ((*_status)[x] == UNMATCHED) {
   4.208 +                augmentOnArc(b);
   4.209 +                return;
   4.210 +              }
   4.211 +            }
   4.212 +          }
   4.213 +        }
   4.214 +      }
   4.215 +    }
   4.216 +
   4.217 +    void processSparse(const Node& n) {
   4.218 +      _process = _last = 0;
   4.219 +      _node_queue[_last++] = n;
   4.220 +      while (_process != _last) {
   4.221 +        Node u = _node_queue[_process++];
   4.222 +        for (OutArcIt a(_graph, u); a != INVALID; ++a) {
   4.223 +          Node v = _graph.target(a);
   4.224 +
   4.225 +          if ((*_status)[v] == EVEN) {
   4.226 +            if (_blossom_set->find(u) != _blossom_set->find(v)) {
   4.227 +              shrinkOnEdge(a);
   4.228 +            }
   4.229 +          } else if ((*_status)[v] == MATCHED) {
   4.230 +            extendOnArc(a);
   4.231 +          } else if ((*_status)[v] == UNMATCHED) {
   4.232 +            augmentOnArc(a);
   4.233 +            return;
   4.234 +          }
   4.235 +        }
   4.236 +      }
   4.237 +    }
   4.238 +
   4.239 +    void shrinkOnEdge(const Edge& e) {
   4.240 +      Node nca = INVALID;
   4.241 +
   4.242 +      {
   4.243 +        std::set<Node> left_set, right_set;
   4.244 +
   4.245 +        Node left = (*_blossom_rep)[_blossom_set->find(_graph.u(e))];
   4.246 +        left_set.insert(left);
   4.247 +
   4.248 +        Node right = (*_blossom_rep)[_blossom_set->find(_graph.v(e))];
   4.249 +        right_set.insert(right);
   4.250 +
   4.251 +        while (true) {
   4.252 +          if ((*_matching)[left] == INVALID) break;
   4.253 +          left = _graph.target((*_matching)[left]);
   4.254 +          left = (*_blossom_rep)[_blossom_set->
   4.255 +                                 find(_graph.target((*_ear)[left]))];
   4.256 +          if (right_set.find(left) != right_set.end()) {
   4.257 +            nca = left;
   4.258 +            break;
   4.259 +          }
   4.260 +          left_set.insert(left);
   4.261 +
   4.262 +          if ((*_matching)[right] == INVALID) break;
   4.263 +          right = _graph.target((*_matching)[right]);
   4.264 +          right = (*_blossom_rep)[_blossom_set->
   4.265 +                                  find(_graph.target((*_ear)[right]))];
   4.266 +          if (left_set.find(right) != left_set.end()) {
   4.267 +            nca = right;
   4.268 +            break;
   4.269 +          }
   4.270 +          right_set.insert(right);
   4.271 +        }
   4.272 +
   4.273 +        if (nca == INVALID) {
   4.274 +          if ((*_matching)[left] == INVALID) {
   4.275 +            nca = right;
   4.276 +            while (left_set.find(nca) == left_set.end()) {
   4.277 +              nca = _graph.target((*_matching)[nca]);
   4.278 +              nca =(*_blossom_rep)[_blossom_set->
   4.279 +                                   find(_graph.target((*_ear)[nca]))];
   4.280 +            }
   4.281 +          } else {
   4.282 +            nca = left;
   4.283 +            while (right_set.find(nca) == right_set.end()) {
   4.284 +              nca = _graph.target((*_matching)[nca]);
   4.285 +              nca = (*_blossom_rep)[_blossom_set->
   4.286 +                                   find(_graph.target((*_ear)[nca]))];
   4.287 +            }
   4.288 +          }
   4.289 +        }
   4.290 +      }
   4.291 +
   4.292 +      {
   4.293 +
   4.294 +        Node node = _graph.u(e);
   4.295 +        Arc arc = _graph.direct(e, true);
   4.296 +        Node base = (*_blossom_rep)[_blossom_set->find(node)];
   4.297 +
   4.298 +        while (base != nca) {
   4.299 +          (*_ear)[node] = arc;
   4.300 +
   4.301 +          Node n = node;
   4.302 +          while (n != base) {
   4.303 +            n = _graph.target((*_matching)[n]);
   4.304 +            Arc a = (*_ear)[n];
   4.305 +            n = _graph.target(a);
   4.306 +            (*_ear)[n] = _graph.oppositeArc(a);
   4.307 +          }
   4.308 +          node = _graph.target((*_matching)[base]);
   4.309 +          _tree_set->erase(base);
   4.310 +          _tree_set->erase(node);
   4.311 +          _blossom_set->insert(node, _blossom_set->find(base));
   4.312 +          (*_status)[node] = EVEN;
   4.313 +          _node_queue[_last++] = node;
   4.314 +          arc = _graph.oppositeArc((*_ear)[node]);
   4.315 +          node = _graph.target((*_ear)[node]);
   4.316 +          base = (*_blossom_rep)[_blossom_set->find(node)];
   4.317 +          _blossom_set->join(_graph.target(arc), base);
   4.318 +        }
   4.319 +      }
   4.320 +
   4.321 +      (*_blossom_rep)[_blossom_set->find(nca)] = nca;
   4.322 +
   4.323 +      {
   4.324 +
   4.325 +        Node node = _graph.v(e);
   4.326 +        Arc arc = _graph.direct(e, false);
   4.327 +        Node base = (*_blossom_rep)[_blossom_set->find(node)];
   4.328 +
   4.329 +        while (base != nca) {
   4.330 +          (*_ear)[node] = arc;
   4.331 +
   4.332 +          Node n = node;
   4.333 +          while (n != base) {
   4.334 +            n = _graph.target((*_matching)[n]);
   4.335 +            Arc a = (*_ear)[n];
   4.336 +            n = _graph.target(a);
   4.337 +            (*_ear)[n] = _graph.oppositeArc(a);
   4.338 +          }
   4.339 +          node = _graph.target((*_matching)[base]);
   4.340 +          _tree_set->erase(base);
   4.341 +          _tree_set->erase(node);
   4.342 +          _blossom_set->insert(node, _blossom_set->find(base));
   4.343 +          (*_status)[node] = EVEN;
   4.344 +          _node_queue[_last++] = node;
   4.345 +          arc = _graph.oppositeArc((*_ear)[node]);
   4.346 +          node = _graph.target((*_ear)[node]);
   4.347 +          base = (*_blossom_rep)[_blossom_set->find(node)];
   4.348 +          _blossom_set->join(_graph.target(arc), base);
   4.349 +        }
   4.350 +      }
   4.351 +
   4.352 +      (*_blossom_rep)[_blossom_set->find(nca)] = nca;
   4.353 +    }
   4.354 +
   4.355 +    void extendOnArc(const Arc& a) {
   4.356 +      Node base = _graph.source(a);
   4.357 +      Node odd = _graph.target(a);
   4.358 +
   4.359 +      (*_ear)[odd] = _graph.oppositeArc(a);
   4.360 +      Node even = _graph.target((*_matching)[odd]);
   4.361 +      (*_blossom_rep)[_blossom_set->insert(even)] = even;
   4.362 +      (*_status)[odd] = ODD;
   4.363 +      (*_status)[even] = EVEN;
   4.364 +      int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(base)]);
   4.365 +      _tree_set->insert(odd, tree);
   4.366 +      _tree_set->insert(even, tree);
   4.367 +      _node_queue[_last++] = even;
   4.368 +
   4.369 +    }
   4.370 +
   4.371 +    void augmentOnArc(const Arc& a) {
   4.372 +      Node even = _graph.source(a);
   4.373 +      Node odd = _graph.target(a);
   4.374 +
   4.375 +      int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(even)]);
   4.376 +
   4.377 +      (*_matching)[odd] = _graph.oppositeArc(a);
   4.378 +      (*_status)[odd] = MATCHED;
   4.379 +
   4.380 +      Arc arc = (*_matching)[even];
   4.381 +      (*_matching)[even] = a;
   4.382 +
   4.383 +      while (arc != INVALID) {
   4.384 +        odd = _graph.target(arc);
   4.385 +        arc = (*_ear)[odd];
   4.386 +        even = _graph.target(arc);
   4.387 +        (*_matching)[odd] = arc;
   4.388 +        arc = (*_matching)[even];
   4.389 +        (*_matching)[even] = _graph.oppositeArc((*_matching)[odd]);
   4.390 +      }
   4.391 +
   4.392 +      for (typename TreeSet::ItemIt it(*_tree_set, tree);
   4.393 +           it != INVALID; ++it) {
   4.394 +        if ((*_status)[it] == ODD) {
   4.395 +          (*_status)[it] = MATCHED;
   4.396 +        } else {
   4.397 +          int blossom = _blossom_set->find(it);
   4.398 +          for (typename BlossomSet::ItemIt jt(*_blossom_set, blossom);
   4.399 +               jt != INVALID; ++jt) {
   4.400 +            (*_status)[jt] = MATCHED;
   4.401 +          }
   4.402 +          _blossom_set->eraseClass(blossom);
   4.403 +        }
   4.404 +      }
   4.405 +      _tree_set->eraseClass(tree);
   4.406 +
   4.407 +    }
   4.408 +
   4.409 +  public:
   4.410 +
   4.411 +    /// \brief Constructor
   4.412 +    ///
   4.413 +    /// Constructor.
   4.414 +    MaxMatching(const Graph& graph)
   4.415 +      : _graph(graph), _matching(0), _status(0), _ear(0),
   4.416 +        _blossom_set_index(0), _blossom_set(0), _blossom_rep(0),
   4.417 +        _tree_set_index(0), _tree_set(0) {}
   4.418 +
   4.419 +    ~MaxMatching() {
   4.420 +      destroyStructures();
   4.421 +    }
   4.422 +
   4.423 +    /// \name Execution Control
   4.424 +    /// The simplest way to execute the algorithm is to use the
   4.425 +    /// \c run() member function.\n
   4.426 +    /// If you need better control on the execution, you have to call
   4.427 +    /// one of the functions \ref init(), \ref greedyInit() or
   4.428 +    /// \ref matchingInit() first, then you can start the algorithm with
   4.429 +    /// \ref startSparse() or \ref startDense().
   4.430 +
   4.431 +    ///@{
   4.432 +
   4.433 +    /// \brief Set the initial matching to the empty matching.
   4.434 +    ///
   4.435 +    /// This function sets the initial matching to the empty matching.
   4.436 +    void init() {
   4.437 +      createStructures();
   4.438 +      for(NodeIt n(_graph); n != INVALID; ++n) {
   4.439 +        (*_matching)[n] = INVALID;
   4.440 +        (*_status)[n] = UNMATCHED;
   4.441 +      }
   4.442 +    }
   4.443 +
   4.444 +    /// \brief Find an initial matching in a greedy way.
   4.445 +    ///
   4.446 +    /// This function finds an initial matching in a greedy way.
   4.447 +    void greedyInit() {
   4.448 +      createStructures();
   4.449 +      for (NodeIt n(_graph); n != INVALID; ++n) {
   4.450 +        (*_matching)[n] = INVALID;
   4.451 +        (*_status)[n] = UNMATCHED;
   4.452 +      }
   4.453 +      for (NodeIt n(_graph); n != INVALID; ++n) {
   4.454 +        if ((*_matching)[n] == INVALID) {
   4.455 +          for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
   4.456 +            Node v = _graph.target(a);
   4.457 +            if ((*_matching)[v] == INVALID && v != n) {
   4.458 +              (*_matching)[n] = a;
   4.459 +              (*_status)[n] = MATCHED;
   4.460 +              (*_matching)[v] = _graph.oppositeArc(a);
   4.461 +              (*_status)[v] = MATCHED;
   4.462 +              break;
   4.463 +            }
   4.464 +          }
   4.465 +        }
   4.466 +      }
   4.467 +    }
   4.468 +
   4.469 +
   4.470 +    /// \brief Initialize the matching from a map.
   4.471 +    ///
   4.472 +    /// This function initializes the matching from a \c bool valued edge
   4.473 +    /// map. This map should have the property that there are no two incident
   4.474 +    /// edges with \c true value, i.e. it really contains a matching.
   4.475 +    /// \return \c true if the map contains a matching.
   4.476 +    template <typename MatchingMap>
   4.477 +    bool matchingInit(const MatchingMap& matching) {
   4.478 +      createStructures();
   4.479 +
   4.480 +      for (NodeIt n(_graph); n != INVALID; ++n) {
   4.481 +        (*_matching)[n] = INVALID;
   4.482 +        (*_status)[n] = UNMATCHED;
   4.483 +      }
   4.484 +      for(EdgeIt e(_graph); e!=INVALID; ++e) {
   4.485 +        if (matching[e]) {
   4.486 +
   4.487 +          Node u = _graph.u(e);
   4.488 +          if ((*_matching)[u] != INVALID) return false;
   4.489 +          (*_matching)[u] = _graph.direct(e, true);
   4.490 +          (*_status)[u] = MATCHED;
   4.491 +
   4.492 +          Node v = _graph.v(e);
   4.493 +          if ((*_matching)[v] != INVALID) return false;
   4.494 +          (*_matching)[v] = _graph.direct(e, false);
   4.495 +          (*_status)[v] = MATCHED;
   4.496 +        }
   4.497 +      }
   4.498 +      return true;
   4.499 +    }
   4.500 +
   4.501 +    /// \brief Start Edmonds' algorithm
   4.502 +    ///
   4.503 +    /// This function runs the original Edmonds' algorithm.
   4.504 +    ///
   4.505 +    /// \pre \ref Init(), \ref greedyInit() or \ref matchingInit() must be
   4.506 +    /// called before using this function.
   4.507 +    void startSparse() {
   4.508 +      for(NodeIt n(_graph); n != INVALID; ++n) {
   4.509 +        if ((*_status)[n] == UNMATCHED) {
   4.510 +          (*_blossom_rep)[_blossom_set->insert(n)] = n;
   4.511 +          _tree_set->insert(n);
   4.512 +          (*_status)[n] = EVEN;
   4.513 +          processSparse(n);
   4.514 +        }
   4.515 +      }
   4.516 +    }
   4.517 +
   4.518 +    /// \brief Start Edmonds' algorithm with a heuristic improvement 
   4.519 +    /// for dense graphs
   4.520 +    ///
   4.521 +    /// This function runs Edmonds' algorithm with a heuristic of postponing
   4.522 +    /// shrinks, therefore resulting in a faster algorithm for dense graphs.
   4.523 +    ///
   4.524 +    /// \pre \ref Init(), \ref greedyInit() or \ref matchingInit() must be
   4.525 +    /// called before using this function.
   4.526 +    void startDense() {
   4.527 +      for(NodeIt n(_graph); n != INVALID; ++n) {
   4.528 +        if ((*_status)[n] == UNMATCHED) {
   4.529 +          (*_blossom_rep)[_blossom_set->insert(n)] = n;
   4.530 +          _tree_set->insert(n);
   4.531 +          (*_status)[n] = EVEN;
   4.532 +          processDense(n);
   4.533 +        }
   4.534 +      }
   4.535 +    }
   4.536 +
   4.537 +
   4.538 +    /// \brief Run Edmonds' algorithm
   4.539 +    ///
   4.540 +    /// This function runs Edmonds' algorithm. An additional heuristic of 
   4.541 +    /// postponing shrinks is used for relatively dense graphs 
   4.542 +    /// (for which <tt>m>=2*n</tt> holds).
   4.543 +    void run() {
   4.544 +      if (countEdges(_graph) < 2 * countNodes(_graph)) {
   4.545 +        greedyInit();
   4.546 +        startSparse();
   4.547 +      } else {
   4.548 +        init();
   4.549 +        startDense();
   4.550 +      }
   4.551 +    }
   4.552 +
   4.553 +    /// @}
   4.554 +
   4.555 +    /// \name Primal Solution
   4.556 +    /// Functions to get the primal solution, i.e. the maximum matching.
   4.557 +
   4.558 +    /// @{
   4.559 +
   4.560 +    /// \brief Return the size (cardinality) of the matching.
   4.561 +    ///
   4.562 +    /// This function returns the size (cardinality) of the current matching. 
   4.563 +    /// After run() it returns the size of the maximum matching in the graph.
   4.564 +    int matchingSize() const {
   4.565 +      int size = 0;
   4.566 +      for (NodeIt n(_graph); n != INVALID; ++n) {
   4.567 +        if ((*_matching)[n] != INVALID) {
   4.568 +          ++size;
   4.569 +        }
   4.570 +      }
   4.571 +      return size / 2;
   4.572 +    }
   4.573 +
   4.574 +    /// \brief Return \c true if the given edge is in the matching.
   4.575 +    ///
   4.576 +    /// This function returns \c true if the given edge is in the current 
   4.577 +    /// matching.
   4.578 +    bool matching(const Edge& edge) const {
   4.579 +      return edge == (*_matching)[_graph.u(edge)];
   4.580 +    }
   4.581 +
   4.582 +    /// \brief Return the matching arc (or edge) incident to the given node.
   4.583 +    ///
   4.584 +    /// This function returns the matching arc (or edge) incident to the
   4.585 +    /// given node in the current matching or \c INVALID if the node is 
   4.586 +    /// not covered by the matching.
   4.587 +    Arc matching(const Node& n) const {
   4.588 +      return (*_matching)[n];
   4.589 +    }
   4.590 +
   4.591 +    /// \brief Return a const reference to the matching map.
   4.592 +    ///
   4.593 +    /// This function returns a const reference to a node map that stores
   4.594 +    /// the matching arc (or edge) incident to each node.
   4.595 +    const MatchingMap& matchingMap() const {
   4.596 +      return *_matching;
   4.597 +    }
   4.598 +
   4.599 +    /// \brief Return the mate of the given node.
   4.600 +    ///
   4.601 +    /// This function returns the mate of the given node in the current 
   4.602 +    /// matching or \c INVALID if the node is not covered by the matching.
   4.603 +    Node mate(const Node& n) const {
   4.604 +      return (*_matching)[n] != INVALID ?
   4.605 +        _graph.target((*_matching)[n]) : INVALID;
   4.606 +    }
   4.607 +
   4.608 +    /// @}
   4.609 +
   4.610 +    /// \name Dual Solution
   4.611 +    /// Functions to get the dual solution, i.e. the Gallai-Edmonds 
   4.612 +    /// decomposition.
   4.613 +
   4.614 +    /// @{
   4.615 +
   4.616 +    /// \brief Return the status of the given node in the Edmonds-Gallai
   4.617 +    /// decomposition.
   4.618 +    ///
   4.619 +    /// This function returns the \ref Status "status" of the given node
   4.620 +    /// in the Edmonds-Gallai decomposition.
   4.621 +    Status status(const Node& n) const {
   4.622 +      return (*_status)[n];
   4.623 +    }
   4.624 +
   4.625 +    /// \brief Return a const reference to the status map, which stores
   4.626 +    /// the Edmonds-Gallai decomposition.
   4.627 +    ///
   4.628 +    /// This function returns a const reference to a node map that stores the
   4.629 +    /// \ref Status "status" of each node in the Edmonds-Gallai decomposition.
   4.630 +    const StatusMap& statusMap() const {
   4.631 +      return *_status;
   4.632 +    }
   4.633 +
   4.634 +    /// \brief Return \c true if the given node is in the barrier.
   4.635 +    ///
   4.636 +    /// This function returns \c true if the given node is in the barrier.
   4.637 +    bool barrier(const Node& n) const {
   4.638 +      return (*_status)[n] == ODD;
   4.639 +    }
   4.640 +
   4.641 +    /// @}
   4.642 +
   4.643 +  };
   4.644 +
   4.645 +  /// \ingroup matching
   4.646 +  ///
   4.647 +  /// \brief Weighted matching in general graphs
   4.648 +  ///
   4.649 +  /// This class provides an efficient implementation of Edmond's
   4.650 +  /// maximum weighted matching algorithm. The implementation is based
   4.651 +  /// on extensive use of priority queues and provides
   4.652 +  /// \f$O(nm\log n)\f$ time complexity.
   4.653 +  ///
   4.654 +  /// The maximum weighted matching problem is to find a subset of the 
   4.655 +  /// edges in an undirected graph with maximum overall weight for which 
   4.656 +  /// each node has at most one incident edge.
   4.657 +  /// It can be formulated with the following linear program.
   4.658 +  /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
   4.659 +  /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
   4.660 +      \quad \forall B\in\mathcal{O}\f] */
   4.661 +  /// \f[x_e \ge 0\quad \forall e\in E\f]
   4.662 +  /// \f[\max \sum_{e\in E}x_ew_e\f]
   4.663 +  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
   4.664 +  /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
   4.665 +  /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
   4.666 +  /// subsets of the nodes.
   4.667 +  ///
   4.668 +  /// The algorithm calculates an optimal matching and a proof of the
   4.669 +  /// optimality. The solution of the dual problem can be used to check
   4.670 +  /// the result of the algorithm. The dual linear problem is the
   4.671 +  /// following.
   4.672 +  /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}
   4.673 +      z_B \ge w_{uv} \quad \forall uv\in E\f] */
   4.674 +  /// \f[y_u \ge 0 \quad \forall u \in V\f]
   4.675 +  /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
   4.676 +  /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
   4.677 +      \frac{\vert B \vert - 1}{2}z_B\f] */
   4.678 +  ///
   4.679 +  /// The algorithm can be executed with the run() function. 
   4.680 +  /// After it the matching (the primal solution) and the dual solution
   4.681 +  /// can be obtained using the query functions and the 
   4.682 +  /// \ref MaxWeightedMatching::BlossomIt "BlossomIt" nested class, 
   4.683 +  /// which is able to iterate on the nodes of a blossom. 
   4.684 +  /// If the value type is integer, then the dual solution is multiplied
   4.685 +  /// by \ref MaxWeightedMatching::dualScale "4".
   4.686 +  ///
   4.687 +  /// \tparam GR The undirected graph type the algorithm runs on.
   4.688 +  /// \tparam WM The type edge weight map. The default type is 
   4.689 +  /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
   4.690 +#ifdef DOXYGEN
   4.691 +  template <typename GR, typename WM>
   4.692 +#else
   4.693 +  template <typename GR,
   4.694 +            typename WM = typename GR::template EdgeMap<int> >
   4.695 +#endif
   4.696 +  class MaxWeightedMatching {
   4.697 +  public:
   4.698 +
   4.699 +    /// The graph type of the algorithm
   4.700 +    typedef GR Graph;
   4.701 +    /// The type of the edge weight map
   4.702 +    typedef WM WeightMap;
   4.703 +    /// The value type of the edge weights
   4.704 +    typedef typename WeightMap::Value Value;
   4.705 +
   4.706 +    /// The type of the matching map
   4.707 +    typedef typename Graph::template NodeMap<typename Graph::Arc>
   4.708 +    MatchingMap;
   4.709 +
   4.710 +    /// \brief Scaling factor for dual solution
   4.711 +    ///
   4.712 +    /// Scaling factor for dual solution. It is equal to 4 or 1
   4.713 +    /// according to the value type.
   4.714 +    static const int dualScale =
   4.715 +      std::numeric_limits<Value>::is_integer ? 4 : 1;
   4.716 +
   4.717 +  private:
   4.718 +
   4.719 +    TEMPLATE_GRAPH_TYPEDEFS(Graph);
   4.720 +
   4.721 +    typedef typename Graph::template NodeMap<Value> NodePotential;
   4.722 +    typedef std::vector<Node> BlossomNodeList;
   4.723 +
   4.724 +    struct BlossomVariable {
   4.725 +      int begin, end;
   4.726 +      Value value;
   4.727 +
   4.728 +      BlossomVariable(int _begin, int _end, Value _value)
   4.729 +        : begin(_begin), end(_end), value(_value) {}
   4.730 +
   4.731 +    };
   4.732 +
   4.733 +    typedef std::vector<BlossomVariable> BlossomPotential;
   4.734 +
   4.735 +    const Graph& _graph;
   4.736 +    const WeightMap& _weight;
   4.737 +
   4.738 +    MatchingMap* _matching;
   4.739 +
   4.740 +    NodePotential* _node_potential;
   4.741 +
   4.742 +    BlossomPotential _blossom_potential;
   4.743 +    BlossomNodeList _blossom_node_list;
   4.744 +
   4.745 +    int _node_num;
   4.746 +    int _blossom_num;
   4.747 +
   4.748 +    typedef RangeMap<int> IntIntMap;
   4.749 +
   4.750 +    enum Status {
   4.751 +      EVEN = -1, MATCHED = 0, ODD = 1, UNMATCHED = -2
   4.752 +    };
   4.753 +
   4.754 +    typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
   4.755 +    struct BlossomData {
   4.756 +      int tree;
   4.757 +      Status status;
   4.758 +      Arc pred, next;
   4.759 +      Value pot, offset;
   4.760 +      Node base;
   4.761 +    };
   4.762 +
   4.763 +    IntNodeMap *_blossom_index;
   4.764 +    BlossomSet *_blossom_set;
   4.765 +    RangeMap<BlossomData>* _blossom_data;
   4.766 +
   4.767 +    IntNodeMap *_node_index;
   4.768 +    IntArcMap *_node_heap_index;
   4.769 +
   4.770 +    struct NodeData {
   4.771 +
   4.772 +      NodeData(IntArcMap& node_heap_index)
   4.773 +        : heap(node_heap_index) {}
   4.774 +
   4.775 +      int blossom;
   4.776 +      Value pot;
   4.777 +      BinHeap<Value, IntArcMap> heap;
   4.778 +      std::map<int, Arc> heap_index;
   4.779 +
   4.780 +      int tree;
   4.781 +    };
   4.782 +
   4.783 +    RangeMap<NodeData>* _node_data;
   4.784 +
   4.785 +    typedef ExtendFindEnum<IntIntMap> TreeSet;
   4.786 +
   4.787 +    IntIntMap *_tree_set_index;
   4.788 +    TreeSet *_tree_set;
   4.789 +
   4.790 +    IntNodeMap *_delta1_index;
   4.791 +    BinHeap<Value, IntNodeMap> *_delta1;
   4.792 +
   4.793 +    IntIntMap *_delta2_index;
   4.794 +    BinHeap<Value, IntIntMap> *_delta2;
   4.795 +
   4.796 +    IntEdgeMap *_delta3_index;
   4.797 +    BinHeap<Value, IntEdgeMap> *_delta3;
   4.798 +
   4.799 +    IntIntMap *_delta4_index;
   4.800 +    BinHeap<Value, IntIntMap> *_delta4;
   4.801 +
   4.802 +    Value _delta_sum;
   4.803 +
   4.804 +    void createStructures() {
   4.805 +      _node_num = countNodes(_graph);
   4.806 +      _blossom_num = _node_num * 3 / 2;
   4.807 +
   4.808 +      if (!_matching) {
   4.809 +        _matching = new MatchingMap(_graph);
   4.810 +      }
   4.811 +      if (!_node_potential) {
   4.812 +        _node_potential = new NodePotential(_graph);
   4.813 +      }
   4.814 +      if (!_blossom_set) {
   4.815 +        _blossom_index = new IntNodeMap(_graph);
   4.816 +        _blossom_set = new BlossomSet(*_blossom_index);
   4.817 +        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
   4.818 +      }
   4.819 +
   4.820 +      if (!_node_index) {
   4.821 +        _node_index = new IntNodeMap(_graph);
   4.822 +        _node_heap_index = new IntArcMap(_graph);
   4.823 +        _node_data = new RangeMap<NodeData>(_node_num,
   4.824 +                                              NodeData(*_node_heap_index));
   4.825 +      }
   4.826 +
   4.827 +      if (!_tree_set) {
   4.828 +        _tree_set_index = new IntIntMap(_blossom_num);
   4.829 +        _tree_set = new TreeSet(*_tree_set_index);
   4.830 +      }
   4.831 +      if (!_delta1) {
   4.832 +        _delta1_index = new IntNodeMap(_graph);
   4.833 +        _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
   4.834 +      }
   4.835 +      if (!_delta2) {
   4.836 +        _delta2_index = new IntIntMap(_blossom_num);
   4.837 +        _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
   4.838 +      }
   4.839 +      if (!_delta3) {
   4.840 +        _delta3_index = new IntEdgeMap(_graph);
   4.841 +        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
   4.842 +      }
   4.843 +      if (!_delta4) {
   4.844 +        _delta4_index = new IntIntMap(_blossom_num);
   4.845 +        _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
   4.846 +      }
   4.847 +    }
   4.848 +
   4.849 +    void destroyStructures() {
   4.850 +      _node_num = countNodes(_graph);
   4.851 +      _blossom_num = _node_num * 3 / 2;
   4.852 +
   4.853 +      if (_matching) {
   4.854 +        delete _matching;
   4.855 +      }
   4.856 +      if (_node_potential) {
   4.857 +        delete _node_potential;
   4.858 +      }
   4.859 +      if (_blossom_set) {
   4.860 +        delete _blossom_index;
   4.861 +        delete _blossom_set;
   4.862 +        delete _blossom_data;
   4.863 +      }
   4.864 +
   4.865 +      if (_node_index) {
   4.866 +        delete _node_index;
   4.867 +        delete _node_heap_index;
   4.868 +        delete _node_data;
   4.869 +      }
   4.870 +
   4.871 +      if (_tree_set) {
   4.872 +        delete _tree_set_index;
   4.873 +        delete _tree_set;
   4.874 +      }
   4.875 +      if (_delta1) {
   4.876 +        delete _delta1_index;
   4.877 +        delete _delta1;
   4.878 +      }
   4.879 +      if (_delta2) {
   4.880 +        delete _delta2_index;
   4.881 +        delete _delta2;
   4.882 +      }
   4.883 +      if (_delta3) {
   4.884 +        delete _delta3_index;
   4.885 +        delete _delta3;
   4.886 +      }
   4.887 +      if (_delta4) {
   4.888 +        delete _delta4_index;
   4.889 +        delete _delta4;
   4.890 +      }
   4.891 +    }
   4.892 +
   4.893 +    void matchedToEven(int blossom, int tree) {
   4.894 +      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
   4.895 +        _delta2->erase(blossom);
   4.896 +      }
   4.897 +
   4.898 +      if (!_blossom_set->trivial(blossom)) {
   4.899 +        (*_blossom_data)[blossom].pot -=
   4.900 +          2 * (_delta_sum - (*_blossom_data)[blossom].offset);
   4.901 +      }
   4.902 +
   4.903 +      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
   4.904 +           n != INVALID; ++n) {
   4.905 +
   4.906 +        _blossom_set->increase(n, std::numeric_limits<Value>::max());
   4.907 +        int ni = (*_node_index)[n];
   4.908 +
   4.909 +        (*_node_data)[ni].heap.clear();
   4.910 +        (*_node_data)[ni].heap_index.clear();
   4.911 +
   4.912 +        (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
   4.913 +
   4.914 +        _delta1->push(n, (*_node_data)[ni].pot);
   4.915 +
   4.916 +        for (InArcIt e(_graph, n); e != INVALID; ++e) {
   4.917 +          Node v = _graph.source(e);
   4.918 +          int vb = _blossom_set->find(v);
   4.919 +          int vi = (*_node_index)[v];
   4.920 +
   4.921 +          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
   4.922 +            dualScale * _weight[e];
   4.923 +
   4.924 +          if ((*_blossom_data)[vb].status == EVEN) {
   4.925 +            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
   4.926 +              _delta3->push(e, rw / 2);
   4.927 +            }
   4.928 +          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
   4.929 +            if (_delta3->state(e) != _delta3->IN_HEAP) {
   4.930 +              _delta3->push(e, rw);
   4.931 +            }
   4.932 +          } else {
   4.933 +            typename std::map<int, Arc>::iterator it =
   4.934 +              (*_node_data)[vi].heap_index.find(tree);
   4.935 +
   4.936 +            if (it != (*_node_data)[vi].heap_index.end()) {
   4.937 +              if ((*_node_data)[vi].heap[it->second] > rw) {
   4.938 +                (*_node_data)[vi].heap.replace(it->second, e);
   4.939 +                (*_node_data)[vi].heap.decrease(e, rw);
   4.940 +                it->second = e;
   4.941 +              }
   4.942 +            } else {
   4.943 +              (*_node_data)[vi].heap.push(e, rw);
   4.944 +              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
   4.945 +            }
   4.946 +
   4.947 +            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
   4.948 +              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
   4.949 +
   4.950 +              if ((*_blossom_data)[vb].status == MATCHED) {
   4.951 +                if (_delta2->state(vb) != _delta2->IN_HEAP) {
   4.952 +                  _delta2->push(vb, _blossom_set->classPrio(vb) -
   4.953 +                               (*_blossom_data)[vb].offset);
   4.954 +                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
   4.955 +                           (*_blossom_data)[vb].offset){
   4.956 +                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
   4.957 +                                   (*_blossom_data)[vb].offset);
   4.958 +                }
   4.959 +              }
   4.960 +            }
   4.961 +          }
   4.962 +        }
   4.963 +      }
   4.964 +      (*_blossom_data)[blossom].offset = 0;
   4.965 +    }
   4.966 +
   4.967 +    void matchedToOdd(int blossom) {
   4.968 +      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
   4.969 +        _delta2->erase(blossom);
   4.970 +      }
   4.971 +      (*_blossom_data)[blossom].offset += _delta_sum;
   4.972 +      if (!_blossom_set->trivial(blossom)) {
   4.973 +        _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
   4.974 +                     (*_blossom_data)[blossom].offset);
   4.975 +      }
   4.976 +    }
   4.977 +
   4.978 +    void evenToMatched(int blossom, int tree) {
   4.979 +      if (!_blossom_set->trivial(blossom)) {
   4.980 +        (*_blossom_data)[blossom].pot += 2 * _delta_sum;
   4.981 +      }
   4.982 +
   4.983 +      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
   4.984 +           n != INVALID; ++n) {
   4.985 +        int ni = (*_node_index)[n];
   4.986 +        (*_node_data)[ni].pot -= _delta_sum;
   4.987 +
   4.988 +        _delta1->erase(n);
   4.989 +
   4.990 +        for (InArcIt e(_graph, n); e != INVALID; ++e) {
   4.991 +          Node v = _graph.source(e);
   4.992 +          int vb = _blossom_set->find(v);
   4.993 +          int vi = (*_node_index)[v];
   4.994 +
   4.995 +          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
   4.996 +            dualScale * _weight[e];
   4.997 +
   4.998 +          if (vb == blossom) {
   4.999 +            if (_delta3->state(e) == _delta3->IN_HEAP) {
  4.1000 +              _delta3->erase(e);
  4.1001 +            }
  4.1002 +          } else if ((*_blossom_data)[vb].status == EVEN) {
  4.1003 +
  4.1004 +            if (_delta3->state(e) == _delta3->IN_HEAP) {
  4.1005 +              _delta3->erase(e);
  4.1006 +            }
  4.1007 +
  4.1008 +            int vt = _tree_set->find(vb);
  4.1009 +
  4.1010 +            if (vt != tree) {
  4.1011 +
  4.1012 +              Arc r = _graph.oppositeArc(e);
  4.1013 +
  4.1014 +              typename std::map<int, Arc>::iterator it =
  4.1015 +                (*_node_data)[ni].heap_index.find(vt);
  4.1016 +
  4.1017 +              if (it != (*_node_data)[ni].heap_index.end()) {
  4.1018 +                if ((*_node_data)[ni].heap[it->second] > rw) {
  4.1019 +                  (*_node_data)[ni].heap.replace(it->second, r);
  4.1020 +                  (*_node_data)[ni].heap.decrease(r, rw);
  4.1021 +                  it->second = r;
  4.1022 +                }
  4.1023 +              } else {
  4.1024 +                (*_node_data)[ni].heap.push(r, rw);
  4.1025 +                (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
  4.1026 +              }
  4.1027 +
  4.1028 +              if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
  4.1029 +                _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
  4.1030 +
  4.1031 +                if (_delta2->state(blossom) != _delta2->IN_HEAP) {
  4.1032 +                  _delta2->push(blossom, _blossom_set->classPrio(blossom) -
  4.1033 +                               (*_blossom_data)[blossom].offset);
  4.1034 +                } else if ((*_delta2)[blossom] >
  4.1035 +                           _blossom_set->classPrio(blossom) -
  4.1036 +                           (*_blossom_data)[blossom].offset){
  4.1037 +                  _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
  4.1038 +                                   (*_blossom_data)[blossom].offset);
  4.1039 +                }
  4.1040 +              }
  4.1041 +            }
  4.1042 +
  4.1043 +          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
  4.1044 +            if (_delta3->state(e) == _delta3->IN_HEAP) {
  4.1045 +              _delta3->erase(e);
  4.1046 +            }
  4.1047 +          } else {
  4.1048 +
  4.1049 +            typename std::map<int, Arc>::iterator it =
  4.1050 +              (*_node_data)[vi].heap_index.find(tree);
  4.1051 +
  4.1052 +            if (it != (*_node_data)[vi].heap_index.end()) {
  4.1053 +              (*_node_data)[vi].heap.erase(it->second);
  4.1054 +              (*_node_data)[vi].heap_index.erase(it);
  4.1055 +              if ((*_node_data)[vi].heap.empty()) {
  4.1056 +                _blossom_set->increase(v, std::numeric_limits<Value>::max());
  4.1057 +              } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
  4.1058 +                _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
  4.1059 +              }
  4.1060 +
  4.1061 +              if ((*_blossom_data)[vb].status == MATCHED) {
  4.1062 +                if (_blossom_set->classPrio(vb) ==
  4.1063 +                    std::numeric_limits<Value>::max()) {
  4.1064 +                  _delta2->erase(vb);
  4.1065 +                } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
  4.1066 +                           (*_blossom_data)[vb].offset) {
  4.1067 +                  _delta2->increase(vb, _blossom_set->classPrio(vb) -
  4.1068 +                                   (*_blossom_data)[vb].offset);
  4.1069 +                }
  4.1070 +              }
  4.1071 +            }
  4.1072 +          }
  4.1073 +        }
  4.1074 +      }
  4.1075 +    }
  4.1076 +
  4.1077 +    void oddToMatched(int blossom) {
  4.1078 +      (*_blossom_data)[blossom].offset -= _delta_sum;
  4.1079 +
  4.1080 +      if (_blossom_set->classPrio(blossom) !=
  4.1081 +          std::numeric_limits<Value>::max()) {
  4.1082 +        _delta2->push(blossom, _blossom_set->classPrio(blossom) -
  4.1083 +                       (*_blossom_data)[blossom].offset);
  4.1084 +      }
  4.1085 +
  4.1086 +      if (!_blossom_set->trivial(blossom)) {
  4.1087 +        _delta4->erase(blossom);
  4.1088 +      }
  4.1089 +    }
  4.1090 +
  4.1091 +    void oddToEven(int blossom, int tree) {
  4.1092 +      if (!_blossom_set->trivial(blossom)) {
  4.1093 +        _delta4->erase(blossom);
  4.1094 +        (*_blossom_data)[blossom].pot -=
  4.1095 +          2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
  4.1096 +      }
  4.1097 +
  4.1098 +      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  4.1099 +           n != INVALID; ++n) {
  4.1100 +        int ni = (*_node_index)[n];
  4.1101 +
  4.1102 +        _blossom_set->increase(n, std::numeric_limits<Value>::max());
  4.1103 +
  4.1104 +        (*_node_data)[ni].heap.clear();
  4.1105 +        (*_node_data)[ni].heap_index.clear();
  4.1106 +        (*_node_data)[ni].pot +=
  4.1107 +          2 * _delta_sum - (*_blossom_data)[blossom].offset;
  4.1108 +
  4.1109 +        _delta1->push(n, (*_node_data)[ni].pot);
  4.1110 +
  4.1111 +        for (InArcIt e(_graph, n); e != INVALID; ++e) {
  4.1112 +          Node v = _graph.source(e);
  4.1113 +          int vb = _blossom_set->find(v);
  4.1114 +          int vi = (*_node_index)[v];
  4.1115 +
  4.1116 +          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  4.1117 +            dualScale * _weight[e];
  4.1118 +
  4.1119 +          if ((*_blossom_data)[vb].status == EVEN) {
  4.1120 +            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
  4.1121 +              _delta3->push(e, rw / 2);
  4.1122 +            }
  4.1123 +          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
  4.1124 +            if (_delta3->state(e) != _delta3->IN_HEAP) {
  4.1125 +              _delta3->push(e, rw);
  4.1126 +            }
  4.1127 +          } else {
  4.1128 +
  4.1129 +            typename std::map<int, Arc>::iterator it =
  4.1130 +              (*_node_data)[vi].heap_index.find(tree);
  4.1131 +
  4.1132 +            if (it != (*_node_data)[vi].heap_index.end()) {
  4.1133 +              if ((*_node_data)[vi].heap[it->second] > rw) {
  4.1134 +                (*_node_data)[vi].heap.replace(it->second, e);
  4.1135 +                (*_node_data)[vi].heap.decrease(e, rw);
  4.1136 +                it->second = e;
  4.1137 +              }
  4.1138 +            } else {
  4.1139 +              (*_node_data)[vi].heap.push(e, rw);
  4.1140 +              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
  4.1141 +            }
  4.1142 +
  4.1143 +            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
  4.1144 +              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
  4.1145 +
  4.1146 +              if ((*_blossom_data)[vb].status == MATCHED) {
  4.1147 +                if (_delta2->state(vb) != _delta2->IN_HEAP) {
  4.1148 +                  _delta2->push(vb, _blossom_set->classPrio(vb) -
  4.1149 +                               (*_blossom_data)[vb].offset);
  4.1150 +                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
  4.1151 +                           (*_blossom_data)[vb].offset) {
  4.1152 +                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
  4.1153 +                                   (*_blossom_data)[vb].offset);
  4.1154 +                }
  4.1155 +              }
  4.1156 +            }
  4.1157 +          }
  4.1158 +        }
  4.1159 +      }
  4.1160 +      (*_blossom_data)[blossom].offset = 0;
  4.1161 +    }
  4.1162 +
  4.1163 +
  4.1164 +    void matchedToUnmatched(int blossom) {
  4.1165 +      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
  4.1166 +        _delta2->erase(blossom);
  4.1167 +      }
  4.1168 +
  4.1169 +      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  4.1170 +           n != INVALID; ++n) {
  4.1171 +        int ni = (*_node_index)[n];
  4.1172 +
  4.1173 +        _blossom_set->increase(n, std::numeric_limits<Value>::max());
  4.1174 +
  4.1175 +        (*_node_data)[ni].heap.clear();
  4.1176 +        (*_node_data)[ni].heap_index.clear();
  4.1177 +
  4.1178 +        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
  4.1179 +          Node v = _graph.target(e);
  4.1180 +          int vb = _blossom_set->find(v);
  4.1181 +          int vi = (*_node_index)[v];
  4.1182 +
  4.1183 +          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  4.1184 +            dualScale * _weight[e];
  4.1185 +
  4.1186 +          if ((*_blossom_data)[vb].status == EVEN) {
  4.1187 +            if (_delta3->state(e) != _delta3->IN_HEAP) {
  4.1188 +              _delta3->push(e, rw);
  4.1189 +            }
  4.1190 +          }
  4.1191 +        }
  4.1192 +      }
  4.1193 +    }
  4.1194 +
  4.1195 +    void unmatchedToMatched(int blossom) {
  4.1196 +      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  4.1197 +           n != INVALID; ++n) {
  4.1198 +        int ni = (*_node_index)[n];
  4.1199 +
  4.1200 +        for (InArcIt e(_graph, n); e != INVALID; ++e) {
  4.1201 +          Node v = _graph.source(e);
  4.1202 +          int vb = _blossom_set->find(v);
  4.1203 +          int vi = (*_node_index)[v];
  4.1204 +
  4.1205 +          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  4.1206 +            dualScale * _weight[e];
  4.1207 +
  4.1208 +          if (vb == blossom) {
  4.1209 +            if (_delta3->state(e) == _delta3->IN_HEAP) {
  4.1210 +              _delta3->erase(e);
  4.1211 +            }
  4.1212 +          } else if ((*_blossom_data)[vb].status == EVEN) {
  4.1213 +
  4.1214 +            if (_delta3->state(e) == _delta3->IN_HEAP) {
  4.1215 +              _delta3->erase(e);
  4.1216 +            }
  4.1217 +
  4.1218 +            int vt = _tree_set->find(vb);
  4.1219 +
  4.1220 +            Arc r = _graph.oppositeArc(e);
  4.1221 +
  4.1222 +            typename std::map<int, Arc>::iterator it =
  4.1223 +              (*_node_data)[ni].heap_index.find(vt);
  4.1224 +
  4.1225 +            if (it != (*_node_data)[ni].heap_index.end()) {
  4.1226 +              if ((*_node_data)[ni].heap[it->second] > rw) {
  4.1227 +                (*_node_data)[ni].heap.replace(it->second, r);
  4.1228 +                (*_node_data)[ni].heap.decrease(r, rw);
  4.1229 +                it->second = r;
  4.1230 +              }
  4.1231 +            } else {
  4.1232 +              (*_node_data)[ni].heap.push(r, rw);
  4.1233 +              (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
  4.1234 +            }
  4.1235 +
  4.1236 +            if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
  4.1237 +              _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
  4.1238 +
  4.1239 +              if (_delta2->state(blossom) != _delta2->IN_HEAP) {
  4.1240 +                _delta2->push(blossom, _blossom_set->classPrio(blossom) -
  4.1241 +                             (*_blossom_data)[blossom].offset);
  4.1242 +              } else if ((*_delta2)[blossom] > _blossom_set->classPrio(blossom)-
  4.1243 +                         (*_blossom_data)[blossom].offset){
  4.1244 +                _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
  4.1245 +                                 (*_blossom_data)[blossom].offset);
  4.1246 +              }
  4.1247 +            }
  4.1248 +
  4.1249 +          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
  4.1250 +            if (_delta3->state(e) == _delta3->IN_HEAP) {
  4.1251 +              _delta3->erase(e);
  4.1252 +            }
  4.1253 +          }
  4.1254 +        }
  4.1255 +      }
  4.1256 +    }
  4.1257 +
  4.1258 +    void alternatePath(int even, int tree) {
  4.1259 +      int odd;
  4.1260 +
  4.1261 +      evenToMatched(even, tree);
  4.1262 +      (*_blossom_data)[even].status = MATCHED;
  4.1263 +
  4.1264 +      while ((*_blossom_data)[even].pred != INVALID) {
  4.1265 +        odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
  4.1266 +        (*_blossom_data)[odd].status = MATCHED;
  4.1267 +        oddToMatched(odd);
  4.1268 +        (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
  4.1269 +
  4.1270 +        even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
  4.1271 +        (*_blossom_data)[even].status = MATCHED;
  4.1272 +        evenToMatched(even, tree);
  4.1273 +        (*_blossom_data)[even].next =
  4.1274 +          _graph.oppositeArc((*_blossom_data)[odd].pred);
  4.1275 +      }
  4.1276 +
  4.1277 +    }
  4.1278 +
  4.1279 +    void destroyTree(int tree) {
  4.1280 +      for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
  4.1281 +        if ((*_blossom_data)[b].status == EVEN) {
  4.1282 +          (*_blossom_data)[b].status = MATCHED;
  4.1283 +          evenToMatched(b, tree);
  4.1284 +        } else if ((*_blossom_data)[b].status == ODD) {
  4.1285 +          (*_blossom_data)[b].status = MATCHED;
  4.1286 +          oddToMatched(b);
  4.1287 +        }
  4.1288 +      }
  4.1289 +      _tree_set->eraseClass(tree);
  4.1290 +    }
  4.1291 +
  4.1292 +
  4.1293 +    void unmatchNode(const Node& node) {
  4.1294 +      int blossom = _blossom_set->find(node);
  4.1295 +      int tree = _tree_set->find(blossom);
  4.1296 +
  4.1297 +      alternatePath(blossom, tree);
  4.1298 +      destroyTree(tree);
  4.1299 +
  4.1300 +      (*_blossom_data)[blossom].status = UNMATCHED;
  4.1301 +      (*_blossom_data)[blossom].base = node;
  4.1302 +      matchedToUnmatched(blossom);
  4.1303 +    }
  4.1304 +
  4.1305 +
  4.1306 +    void augmentOnEdge(const Edge& edge) {
  4.1307 +
  4.1308 +      int left = _blossom_set->find(_graph.u(edge));
  4.1309 +      int right = _blossom_set->find(_graph.v(edge));
  4.1310 +
  4.1311 +      if ((*_blossom_data)[left].status == EVEN) {
  4.1312 +        int left_tree = _tree_set->find(left);
  4.1313 +        alternatePath(left, left_tree);
  4.1314 +        destroyTree(left_tree);
  4.1315 +      } else {
  4.1316 +        (*_blossom_data)[left].status = MATCHED;
  4.1317 +        unmatchedToMatched(left);
  4.1318 +      }
  4.1319 +
  4.1320 +      if ((*_blossom_data)[right].status == EVEN) {
  4.1321 +        int right_tree = _tree_set->find(right);
  4.1322 +        alternatePath(right, right_tree);
  4.1323 +        destroyTree(right_tree);
  4.1324 +      } else {
  4.1325 +        (*_blossom_data)[right].status = MATCHED;
  4.1326 +        unmatchedToMatched(right);
  4.1327 +      }
  4.1328 +
  4.1329 +      (*_blossom_data)[left].next = _graph.direct(edge, true);
  4.1330 +      (*_blossom_data)[right].next = _graph.direct(edge, false);
  4.1331 +    }
  4.1332 +
  4.1333 +    void extendOnArc(const Arc& arc) {
  4.1334 +      int base = _blossom_set->find(_graph.target(arc));
  4.1335 +      int tree = _tree_set->find(base);
  4.1336 +
  4.1337 +      int odd = _blossom_set->find(_graph.source(arc));
  4.1338 +      _tree_set->insert(odd, tree);
  4.1339 +      (*_blossom_data)[odd].status = ODD;
  4.1340 +      matchedToOdd(odd);
  4.1341 +      (*_blossom_data)[odd].pred = arc;
  4.1342 +
  4.1343 +      int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
  4.1344 +      (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
  4.1345 +      _tree_set->insert(even, tree);
  4.1346 +      (*_blossom_data)[even].status = EVEN;
  4.1347 +      matchedToEven(even, tree);
  4.1348 +    }
  4.1349 +
  4.1350 +    void shrinkOnEdge(const Edge& edge, int tree) {
  4.1351 +      int nca = -1;
  4.1352 +      std::vector<int> left_path, right_path;
  4.1353 +
  4.1354 +      {
  4.1355 +        std::set<int> left_set, right_set;
  4.1356 +        int left = _blossom_set->find(_graph.u(edge));
  4.1357 +        left_path.push_back(left);
  4.1358 +        left_set.insert(left);
  4.1359 +
  4.1360 +        int right = _blossom_set->find(_graph.v(edge));
  4.1361 +        right_path.push_back(right);
  4.1362 +        right_set.insert(right);
  4.1363 +
  4.1364 +        while (true) {
  4.1365 +
  4.1366 +          if ((*_blossom_data)[left].pred == INVALID) break;
  4.1367 +
  4.1368 +          left =
  4.1369 +            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
  4.1370 +          left_path.push_back(left);
  4.1371 +          left =
  4.1372 +            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
  4.1373 +          left_path.push_back(left);
  4.1374 +
  4.1375 +          left_set.insert(left);
  4.1376 +
  4.1377 +          if (right_set.find(left) != right_set.end()) {
  4.1378 +            nca = left;
  4.1379 +            break;
  4.1380 +          }
  4.1381 +
  4.1382 +          if ((*_blossom_data)[right].pred == INVALID) break;
  4.1383 +
  4.1384 +          right =
  4.1385 +            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
  4.1386 +          right_path.push_back(right);
  4.1387 +          right =
  4.1388 +            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
  4.1389 +          right_path.push_back(right);
  4.1390 +
  4.1391 +          right_set.insert(right);
  4.1392 +
  4.1393 +          if (left_set.find(right) != left_set.end()) {
  4.1394 +            nca = right;
  4.1395 +            break;
  4.1396 +          }
  4.1397 +
  4.1398 +        }
  4.1399 +
  4.1400 +        if (nca == -1) {
  4.1401 +          if ((*_blossom_data)[left].pred == INVALID) {
  4.1402 +            nca = right;
  4.1403 +            while (left_set.find(nca) == left_set.end()) {
  4.1404 +              nca =
  4.1405 +                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  4.1406 +              right_path.push_back(nca);
  4.1407 +              nca =
  4.1408 +                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  4.1409 +              right_path.push_back(nca);
  4.1410 +            }
  4.1411 +          } else {
  4.1412 +            nca = left;
  4.1413 +            while (right_set.find(nca) == right_set.end()) {
  4.1414 +              nca =
  4.1415 +                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  4.1416 +              left_path.push_back(nca);
  4.1417 +              nca =
  4.1418 +                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  4.1419 +              left_path.push_back(nca);
  4.1420 +            }
  4.1421 +          }
  4.1422 +        }
  4.1423 +      }
  4.1424 +
  4.1425 +      std::vector<int> subblossoms;
  4.1426 +      Arc prev;
  4.1427 +
  4.1428 +      prev = _graph.direct(edge, true);
  4.1429 +      for (int i = 0; left_path[i] != nca; i += 2) {
  4.1430 +        subblossoms.push_back(left_path[i]);
  4.1431 +        (*_blossom_data)[left_path[i]].next = prev;
  4.1432 +        _tree_set->erase(left_path[i]);
  4.1433 +
  4.1434 +        subblossoms.push_back(left_path[i + 1]);
  4.1435 +        (*_blossom_data)[left_path[i + 1]].status = EVEN;
  4.1436 +        oddToEven(left_path[i + 1], tree);
  4.1437 +        _tree_set->erase(left_path[i + 1]);
  4.1438 +        prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
  4.1439 +      }
  4.1440 +
  4.1441 +      int k = 0;
  4.1442 +      while (right_path[k] != nca) ++k;
  4.1443 +
  4.1444 +      subblossoms.push_back(nca);
  4.1445 +      (*_blossom_data)[nca].next = prev;
  4.1446 +
  4.1447 +      for (int i = k - 2; i >= 0; i -= 2) {
  4.1448 +        subblossoms.push_back(right_path[i + 1]);
  4.1449 +        (*_blossom_data)[right_path[i + 1]].status = EVEN;
  4.1450 +        oddToEven(right_path[i + 1], tree);
  4.1451 +        _tree_set->erase(right_path[i + 1]);
  4.1452 +
  4.1453 +        (*_blossom_data)[right_path[i + 1]].next =
  4.1454 +          (*_blossom_data)[right_path[i + 1]].pred;
  4.1455 +
  4.1456 +        subblossoms.push_back(right_path[i]);
  4.1457 +        _tree_set->erase(right_path[i]);
  4.1458 +      }
  4.1459 +
  4.1460 +      int surface =
  4.1461 +        _blossom_set->join(subblossoms.begin(), subblossoms.end());
  4.1462 +
  4.1463 +      for (int i = 0; i < int(subblossoms.size()); ++i) {
  4.1464 +        if (!_blossom_set->trivial(subblossoms[i])) {
  4.1465 +          (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
  4.1466 +        }
  4.1467 +        (*_blossom_data)[subblossoms[i]].status = MATCHED;
  4.1468 +      }
  4.1469 +
  4.1470 +      (*_blossom_data)[surface].pot = -2 * _delta_sum;
  4.1471 +      (*_blossom_data)[surface].offset = 0;
  4.1472 +      (*_blossom_data)[surface].status = EVEN;
  4.1473 +      (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
  4.1474 +      (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
  4.1475 +
  4.1476 +      _tree_set->insert(surface, tree);
  4.1477 +      _tree_set->erase(nca);
  4.1478 +    }
  4.1479 +
  4.1480 +    void splitBlossom(int blossom) {
  4.1481 +      Arc next = (*_blossom_data)[blossom].next;
  4.1482 +      Arc pred = (*_blossom_data)[blossom].pred;
  4.1483 +
  4.1484 +      int tree = _tree_set->find(blossom);
  4.1485 +
  4.1486 +      (*_blossom_data)[blossom].status = MATCHED;
  4.1487 +      oddToMatched(blossom);
  4.1488 +      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
  4.1489 +        _delta2->erase(blossom);
  4.1490 +      }
  4.1491 +
  4.1492 +      std::vector<int> subblossoms;
  4.1493 +      _blossom_set->split(blossom, std::back_inserter(subblossoms));
  4.1494 +
  4.1495 +      Value offset = (*_blossom_data)[blossom].offset;
  4.1496 +      int b = _blossom_set->find(_graph.source(pred));
  4.1497 +      int d = _blossom_set->find(_graph.source(next));
  4.1498 +
  4.1499 +      int ib = -1, id = -1;
  4.1500 +      for (int i = 0; i < int(subblossoms.size()); ++i) {
  4.1501 +        if (subblossoms[i] == b) ib = i;
  4.1502 +        if (subblossoms[i] == d) id = i;
  4.1503 +
  4.1504 +        (*_blossom_data)[subblossoms[i]].offset = offset;
  4.1505 +        if (!_blossom_set->trivial(subblossoms[i])) {
  4.1506 +          (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
  4.1507 +        }
  4.1508 +        if (_blossom_set->classPrio(subblossoms[i]) !=
  4.1509 +            std::numeric_limits<Value>::max()) {
  4.1510 +          _delta2->push(subblossoms[i],
  4.1511 +                        _blossom_set->classPrio(subblossoms[i]) -
  4.1512 +                        (*_blossom_data)[subblossoms[i]].offset);
  4.1513 +        }
  4.1514 +      }
  4.1515 +
  4.1516 +      if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
  4.1517 +        for (int i = (id + 1) % subblossoms.size();
  4.1518 +             i != ib; i = (i + 2) % subblossoms.size()) {
  4.1519 +          int sb = subblossoms[i];
  4.1520 +          int tb = subblossoms[(i + 1) % subblossoms.size()];
  4.1521 +          (*_blossom_data)[sb].next =
  4.1522 +            _graph.oppositeArc((*_blossom_data)[tb].next);
  4.1523 +        }
  4.1524 +
  4.1525 +        for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
  4.1526 +          int sb = subblossoms[i];
  4.1527 +          int tb = subblossoms[(i + 1) % subblossoms.size()];
  4.1528 +          int ub = subblossoms[(i + 2) % subblossoms.size()];
  4.1529 +
  4.1530 +          (*_blossom_data)[sb].status = ODD;
  4.1531 +          matchedToOdd(sb);
  4.1532 +          _tree_set->insert(sb, tree);
  4.1533 +          (*_blossom_data)[sb].pred = pred;
  4.1534 +          (*_blossom_data)[sb].next =
  4.1535 +                           _graph.oppositeArc((*_blossom_data)[tb].next);
  4.1536 +
  4.1537 +          pred = (*_blossom_data)[ub].next;
  4.1538 +
  4.1539 +          (*_blossom_data)[tb].status = EVEN;
  4.1540 +          matchedToEven(tb, tree);
  4.1541 +          _tree_set->insert(tb, tree);
  4.1542 +          (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
  4.1543 +        }
  4.1544 +
  4.1545 +        (*_blossom_data)[subblossoms[id]].status = ODD;
  4.1546 +        matchedToOdd(subblossoms[id]);
  4.1547 +        _tree_set->insert(subblossoms[id], tree);
  4.1548 +        (*_blossom_data)[subblossoms[id]].next = next;
  4.1549 +        (*_blossom_data)[subblossoms[id]].pred = pred;
  4.1550 +
  4.1551 +      } else {
  4.1552 +
  4.1553 +        for (int i = (ib + 1) % subblossoms.size();
  4.1554 +             i != id; i = (i + 2) % subblossoms.size()) {
  4.1555 +          int sb = subblossoms[i];
  4.1556 +          int tb = subblossoms[(i + 1) % subblossoms.size()];
  4.1557 +          (*_blossom_data)[sb].next =
  4.1558 +            _graph.oppositeArc((*_blossom_data)[tb].next);
  4.1559 +        }
  4.1560 +
  4.1561 +        for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
  4.1562 +          int sb = subblossoms[i];
  4.1563 +          int tb = subblossoms[(i + 1) % subblossoms.size()];
  4.1564 +          int ub = subblossoms[(i + 2) % subblossoms.size()];
  4.1565 +
  4.1566 +          (*_blossom_data)[sb].status = ODD;
  4.1567 +          matchedToOdd(sb);
  4.1568 +          _tree_set->insert(sb, tree);
  4.1569 +          (*_blossom_data)[sb].next = next;
  4.1570 +          (*_blossom_data)[sb].pred =
  4.1571 +            _graph.oppositeArc((*_blossom_data)[tb].next);
  4.1572 +
  4.1573 +          (*_blossom_data)[tb].status = EVEN;
  4.1574 +          matchedToEven(tb, tree);
  4.1575 +          _tree_set->insert(tb, tree);
  4.1576 +          (*_blossom_data)[tb].pred =
  4.1577 +            (*_blossom_data)[tb].next =
  4.1578 +            _graph.oppositeArc((*_blossom_data)[ub].next);
  4.1579 +          next = (*_blossom_data)[ub].next;
  4.1580 +        }
  4.1581 +
  4.1582 +        (*_blossom_data)[subblossoms[ib]].status = ODD;
  4.1583 +        matchedToOdd(subblossoms[ib]);
  4.1584 +        _tree_set->insert(subblossoms[ib], tree);
  4.1585 +        (*_blossom_data)[subblossoms[ib]].next = next;
  4.1586 +        (*_blossom_data)[subblossoms[ib]].pred = pred;
  4.1587 +      }
  4.1588 +      _tree_set->erase(blossom);
  4.1589 +    }
  4.1590 +
  4.1591 +    void extractBlossom(int blossom, const Node& base, const Arc& matching) {
  4.1592 +      if (_blossom_set->trivial(blossom)) {
  4.1593 +        int bi = (*_node_index)[base];
  4.1594 +        Value pot = (*_node_data)[bi].pot;
  4.1595 +
  4.1596 +        (*_matching)[base] = matching;
  4.1597 +        _blossom_node_list.push_back(base);
  4.1598 +        (*_node_potential)[base] = pot;
  4.1599 +      } else {
  4.1600 +
  4.1601 +        Value pot = (*_blossom_data)[blossom].pot;
  4.1602 +        int bn = _blossom_node_list.size();
  4.1603 +
  4.1604 +        std::vector<int> subblossoms;
  4.1605 +        _blossom_set->split(blossom, std::back_inserter(subblossoms));
  4.1606 +        int b = _blossom_set->find(base);
  4.1607 +        int ib = -1;
  4.1608 +        for (int i = 0; i < int(subblossoms.size()); ++i) {
  4.1609 +          if (subblossoms[i] == b) { ib = i; break; }
  4.1610 +        }
  4.1611 +
  4.1612 +        for (int i = 1; i < int(subblossoms.size()); i += 2) {
  4.1613 +          int sb = subblossoms[(ib + i) % subblossoms.size()];
  4.1614 +          int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
  4.1615 +
  4.1616 +          Arc m = (*_blossom_data)[tb].next;
  4.1617 +          extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
  4.1618 +          extractBlossom(tb, _graph.source(m), m);
  4.1619 +        }
  4.1620 +        extractBlossom(subblossoms[ib], base, matching);
  4.1621 +
  4.1622 +        int en = _blossom_node_list.size();
  4.1623 +
  4.1624 +        _blossom_potential.push_back(BlossomVariable(bn, en, pot));
  4.1625 +      }
  4.1626 +    }
  4.1627 +
  4.1628 +    void extractMatching() {
  4.1629 +      std::vector<int> blossoms;
  4.1630 +      for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
  4.1631 +        blossoms.push_back(c);
  4.1632 +      }
  4.1633 +
  4.1634 +      for (int i = 0; i < int(blossoms.size()); ++i) {
  4.1635 +        if ((*_blossom_data)[blossoms[i]].status == MATCHED) {
  4.1636 +
  4.1637 +          Value offset = (*_blossom_data)[blossoms[i]].offset;
  4.1638 +          (*_blossom_data)[blossoms[i]].pot += 2 * offset;
  4.1639 +          for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
  4.1640 +               n != INVALID; ++n) {
  4.1641 +            (*_node_data)[(*_node_index)[n]].pot -= offset;
  4.1642 +          }
  4.1643 +
  4.1644 +          Arc matching = (*_blossom_data)[blossoms[i]].next;
  4.1645 +          Node base = _graph.source(matching);
  4.1646 +          extractBlossom(blossoms[i], base, matching);
  4.1647 +        } else {
  4.1648 +          Node base = (*_blossom_data)[blossoms[i]].base;
  4.1649 +          extractBlossom(blossoms[i], base, INVALID);
  4.1650 +        }
  4.1651 +      }
  4.1652 +    }
  4.1653 +
  4.1654 +  public:
  4.1655 +
  4.1656 +    /// \brief Constructor
  4.1657 +    ///
  4.1658 +    /// Constructor.
  4.1659 +    MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
  4.1660 +      : _graph(graph), _weight(weight), _matching(0),
  4.1661 +        _node_potential(0), _blossom_potential(), _blossom_node_list(),
  4.1662 +        _node_num(0), _blossom_num(0),
  4.1663 +
  4.1664 +        _blossom_index(0), _blossom_set(0), _blossom_data(0),
  4.1665 +        _node_index(0), _node_heap_index(0), _node_data(0),
  4.1666 +        _tree_set_index(0), _tree_set(0),
  4.1667 +
  4.1668 +        _delta1_index(0), _delta1(0),
  4.1669 +        _delta2_index(0), _delta2(0),
  4.1670 +        _delta3_index(0), _delta3(0),
  4.1671 +        _delta4_index(0), _delta4(0),
  4.1672 +
  4.1673 +        _delta_sum() {}
  4.1674 +
  4.1675 +    ~MaxWeightedMatching() {
  4.1676 +      destroyStructures();
  4.1677 +    }
  4.1678 +
  4.1679 +    /// \name Execution Control
  4.1680 +    /// The simplest way to execute the algorithm is to use the
  4.1681 +    /// \ref run() member function.
  4.1682 +
  4.1683 +    ///@{
  4.1684 +
  4.1685 +    /// \brief Initialize the algorithm
  4.1686 +    ///
  4.1687 +    /// This function initializes the algorithm.
  4.1688 +    void init() {
  4.1689 +      createStructures();
  4.1690 +
  4.1691 +      for (ArcIt e(_graph); e != INVALID; ++e) {
  4.1692 +        (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
  4.1693 +      }
  4.1694 +      for (NodeIt n(_graph); n != INVALID; ++n) {
  4.1695 +        (*_delta1_index)[n] = _delta1->PRE_HEAP;
  4.1696 +      }
  4.1697 +      for (EdgeIt e(_graph); e != INVALID; ++e) {
  4.1698 +        (*_delta3_index)[e] = _delta3->PRE_HEAP;
  4.1699 +      }
  4.1700 +      for (int i = 0; i < _blossom_num; ++i) {
  4.1701 +        (*_delta2_index)[i] = _delta2->PRE_HEAP;
  4.1702 +        (*_delta4_index)[i] = _delta4->PRE_HEAP;
  4.1703 +      }
  4.1704 +
  4.1705 +      int index = 0;
  4.1706 +      for (NodeIt n(_graph); n != INVALID; ++n) {
  4.1707 +        Value max = 0;
  4.1708 +        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
  4.1709 +          if (_graph.target(e) == n) continue;
  4.1710 +          if ((dualScale * _weight[e]) / 2 > max) {
  4.1711 +            max = (dualScale * _weight[e]) / 2;
  4.1712 +          }
  4.1713 +        }
  4.1714 +        (*_node_index)[n] = index;
  4.1715 +        (*_node_data)[index].pot = max;
  4.1716 +        _delta1->push(n, max);
  4.1717 +        int blossom =
  4.1718 +          _blossom_set->insert(n, std::numeric_limits<Value>::max());
  4.1719 +
  4.1720 +        _tree_set->insert(blossom);
  4.1721 +
  4.1722 +        (*_blossom_data)[blossom].status = EVEN;
  4.1723 +        (*_blossom_data)[blossom].pred = INVALID;
  4.1724 +        (*_blossom_data)[blossom].next = INVALID;
  4.1725 +        (*_blossom_data)[blossom].pot = 0;
  4.1726 +        (*_blossom_data)[blossom].offset = 0;
  4.1727 +        ++index;
  4.1728 +      }
  4.1729 +      for (EdgeIt e(_graph); e != INVALID; ++e) {
  4.1730 +        int si = (*_node_index)[_graph.u(e)];
  4.1731 +        int ti = (*_node_index)[_graph.v(e)];
  4.1732 +        if (_graph.u(e) != _graph.v(e)) {
  4.1733 +          _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
  4.1734 +                            dualScale * _weight[e]) / 2);
  4.1735 +        }
  4.1736 +      }
  4.1737 +    }
  4.1738 +
  4.1739 +    /// \brief Start the algorithm
  4.1740 +    ///
  4.1741 +    /// This function starts the algorithm.
  4.1742 +    ///
  4.1743 +    /// \pre \ref init() must be called before using this function.
  4.1744 +    void start() {
  4.1745 +      enum OpType {
  4.1746 +        D1, D2, D3, D4
  4.1747 +      };
  4.1748 +
  4.1749 +      int unmatched = _node_num;
  4.1750 +      while (unmatched > 0) {
  4.1751 +        Value d1 = !_delta1->empty() ?
  4.1752 +          _delta1->prio() : std::numeric_limits<Value>::max();
  4.1753 +
  4.1754 +        Value d2 = !_delta2->empty() ?
  4.1755 +          _delta2->prio() : std::numeric_limits<Value>::max();
  4.1756 +
  4.1757 +        Value d3 = !_delta3->empty() ?
  4.1758 +          _delta3->prio() : std::numeric_limits<Value>::max();
  4.1759 +
  4.1760 +        Value d4 = !_delta4->empty() ?
  4.1761 +          _delta4->prio() : std::numeric_limits<Value>::max();
  4.1762 +
  4.1763 +        _delta_sum = d1; OpType ot = D1;
  4.1764 +        if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
  4.1765 +        if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
  4.1766 +        if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
  4.1767 +
  4.1768 +
  4.1769 +        switch (ot) {
  4.1770 +        case D1:
  4.1771 +          {
  4.1772 +            Node n = _delta1->top();
  4.1773 +            unmatchNode(n);
  4.1774 +            --unmatched;
  4.1775 +          }
  4.1776 +          break;
  4.1777 +        case D2:
  4.1778 +          {
  4.1779 +            int blossom = _delta2->top();
  4.1780 +            Node n = _blossom_set->classTop(blossom);
  4.1781 +            Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
  4.1782 +            extendOnArc(e);
  4.1783 +          }
  4.1784 +          break;
  4.1785 +        case D3:
  4.1786 +          {
  4.1787 +            Edge e = _delta3->top();
  4.1788 +
  4.1789 +            int left_blossom = _blossom_set->find(_graph.u(e));
  4.1790 +            int right_blossom = _blossom_set->find(_graph.v(e));
  4.1791 +
  4.1792 +            if (left_blossom == right_blossom) {
  4.1793 +              _delta3->pop();
  4.1794 +            } else {
  4.1795 +              int left_tree;
  4.1796 +              if ((*_blossom_data)[left_blossom].status == EVEN) {
  4.1797 +                left_tree = _tree_set->find(left_blossom);
  4.1798 +              } else {
  4.1799 +                left_tree = -1;
  4.1800 +                ++unmatched;
  4.1801 +              }
  4.1802 +              int right_tree;
  4.1803 +              if ((*_blossom_data)[right_blossom].status == EVEN) {
  4.1804 +                right_tree = _tree_set->find(right_blossom);
  4.1805 +              } else {
  4.1806 +                right_tree = -1;
  4.1807 +                ++unmatched;
  4.1808 +              }
  4.1809 +
  4.1810 +              if (left_tree == right_tree) {
  4.1811 +                shrinkOnEdge(e, left_tree);
  4.1812 +              } else {
  4.1813 +                augmentOnEdge(e);
  4.1814 +                unmatched -= 2;
  4.1815 +              }
  4.1816 +            }
  4.1817 +          } break;
  4.1818 +        case D4:
  4.1819 +          splitBlossom(_delta4->top());
  4.1820 +          break;
  4.1821 +        }
  4.1822 +      }
  4.1823 +      extractMatching();
  4.1824 +    }
  4.1825 +
  4.1826 +    /// \brief Run the algorithm.
  4.1827 +    ///
  4.1828 +    /// This method runs the \c %MaxWeightedMatching algorithm.
  4.1829 +    ///
  4.1830 +    /// \note mwm.run() is just a shortcut of the following code.
  4.1831 +    /// \code
  4.1832 +    ///   mwm.init();
  4.1833 +    ///   mwm.start();
  4.1834 +    /// \endcode
  4.1835 +    void run() {
  4.1836 +      init();
  4.1837 +      start();
  4.1838 +    }
  4.1839 +
  4.1840 +    /// @}
  4.1841 +
  4.1842 +    /// \name Primal Solution
  4.1843 +    /// Functions to get the primal solution, i.e. the maximum weighted 
  4.1844 +    /// matching.\n
  4.1845 +    /// Either \ref run() or \ref start() function should be called before
  4.1846 +    /// using them.
  4.1847 +
  4.1848 +    /// @{
  4.1849 +
  4.1850 +    /// \brief Return the weight of the matching.
  4.1851 +    ///
  4.1852 +    /// This function returns the weight of the found matching.
  4.1853 +    ///
  4.1854 +    /// \pre Either run() or start() must be called before using this function.
  4.1855 +    Value matchingWeight() const {
  4.1856 +      Value sum = 0;
  4.1857 +      for (NodeIt n(_graph); n != INVALID; ++n) {
  4.1858 +        if ((*_matching)[n] != INVALID) {
  4.1859 +          sum += _weight[(*_matching)[n]];
  4.1860 +        }
  4.1861 +      }
  4.1862 +      return sum /= 2;
  4.1863 +    }
  4.1864 +
  4.1865 +    /// \brief Return the size (cardinality) of the matching.
  4.1866 +    ///
  4.1867 +    /// This function returns the size (cardinality) of the found matching.
  4.1868 +    ///
  4.1869 +    /// \pre Either run() or start() must be called before using this function.
  4.1870 +    int matchingSize() const {
  4.1871 +      int num = 0;
  4.1872 +      for (NodeIt n(_graph); n != INVALID; ++n) {
  4.1873 +        if ((*_matching)[n] != INVALID) {
  4.1874 +          ++num;
  4.1875 +        }
  4.1876 +      }
  4.1877 +      return num /= 2;
  4.1878 +    }
  4.1879 +
  4.1880 +    /// \brief Return \c true if the given edge is in the matching.
  4.1881 +    ///
  4.1882 +    /// This function returns \c true if the given edge is in the found 
  4.1883 +    /// matching.
  4.1884 +    ///
  4.1885 +    /// \pre Either run() or start() must be called before using this function.
  4.1886 +    bool matching(const Edge& edge) const {
  4.1887 +      return edge == (*_matching)[_graph.u(edge)];
  4.1888 +    }
  4.1889 +
  4.1890 +    /// \brief Return the matching arc (or edge) incident to the given node.
  4.1891 +    ///
  4.1892 +    /// This function returns the matching arc (or edge) incident to the
  4.1893 +    /// given node in the found matching or \c INVALID if the node is 
  4.1894 +    /// not covered by the matching.
  4.1895 +    ///
  4.1896 +    /// \pre Either run() or start() must be called before using this function.
  4.1897 +    Arc matching(const Node& node) const {
  4.1898 +      return (*_matching)[node];
  4.1899 +    }
  4.1900 +
  4.1901 +    /// \brief Return a const reference to the matching map.
  4.1902 +    ///
  4.1903 +    /// This function returns a const reference to a node map that stores
  4.1904 +    /// the matching arc (or edge) incident to each node.
  4.1905 +    const MatchingMap& matchingMap() const {
  4.1906 +      return *_matching;
  4.1907 +    }
  4.1908 +
  4.1909 +    /// \brief Return the mate of the given node.
  4.1910 +    ///
  4.1911 +    /// This function returns the mate of the given node in the found 
  4.1912 +    /// matching or \c INVALID if the node is not covered by the matching.
  4.1913 +    ///
  4.1914 +    /// \pre Either run() or start() must be called before using this function.
  4.1915 +    Node mate(const Node& node) const {
  4.1916 +      return (*_matching)[node] != INVALID ?
  4.1917 +        _graph.target((*_matching)[node]) : INVALID;
  4.1918 +    }
  4.1919 +
  4.1920 +    /// @}
  4.1921 +
  4.1922 +    /// \name Dual Solution
  4.1923 +    /// Functions to get the dual solution.\n
  4.1924 +    /// Either \ref run() or \ref start() function should be called before
  4.1925 +    /// using them.
  4.1926 +
  4.1927 +    /// @{
  4.1928 +
  4.1929 +    /// \brief Return the value of the dual solution.
  4.1930 +    ///
  4.1931 +    /// This function returns the value of the dual solution. 
  4.1932 +    /// It should be equal to the primal value scaled by \ref dualScale 
  4.1933 +    /// "dual scale".
  4.1934 +    ///
  4.1935 +    /// \pre Either run() or start() must be called before using this function.
  4.1936 +    Value dualValue() const {
  4.1937 +      Value sum = 0;
  4.1938 +      for (NodeIt n(_graph); n != INVALID; ++n) {
  4.1939 +        sum += nodeValue(n);
  4.1940 +      }
  4.1941 +      for (int i = 0; i < blossomNum(); ++i) {
  4.1942 +        sum += blossomValue(i) * (blossomSize(i) / 2);
  4.1943 +      }
  4.1944 +      return sum;
  4.1945 +    }
  4.1946 +
  4.1947 +    /// \brief Return the dual value (potential) of the given node.
  4.1948 +    ///
  4.1949 +    /// This function returns the dual value (potential) of the given node.
  4.1950 +    ///
  4.1951 +    /// \pre Either run() or start() must be called before using this function.
  4.1952 +    Value nodeValue(const Node& n) const {
  4.1953 +      return (*_node_potential)[n];
  4.1954 +    }
  4.1955 +
  4.1956 +    /// \brief Return the number of the blossoms in the basis.
  4.1957 +    ///
  4.1958 +    /// This function returns the number of the blossoms in the basis.
  4.1959 +    ///
  4.1960 +    /// \pre Either run() or start() must be called before using this function.
  4.1961 +    /// \see BlossomIt
  4.1962 +    int blossomNum() const {
  4.1963 +      return _blossom_potential.size();
  4.1964 +    }
  4.1965 +
  4.1966 +    /// \brief Return the number of the nodes in the given blossom.
  4.1967 +    ///
  4.1968 +    /// This function returns the number of the nodes in the given blossom.
  4.1969 +    ///
  4.1970 +    /// \pre Either run() or start() must be called before using this function.
  4.1971 +    /// \see BlossomIt
  4.1972 +    int blossomSize(int k) const {
  4.1973 +      return _blossom_potential[k].end - _blossom_potential[k].begin;
  4.1974 +    }
  4.1975 +
  4.1976 +    /// \brief Return the dual value (ptential) of the given blossom.
  4.1977 +    ///
  4.1978 +    /// This function returns the dual value (ptential) of the given blossom.
  4.1979 +    ///
  4.1980 +    /// \pre Either run() or start() must be called before using this function.
  4.1981 +    Value blossomValue(int k) const {
  4.1982 +      return _blossom_potential[k].value;
  4.1983 +    }
  4.1984 +
  4.1985 +    /// \brief Iterator for obtaining the nodes of a blossom.
  4.1986 +    ///
  4.1987 +    /// This class provides an iterator for obtaining the nodes of the 
  4.1988 +    /// given blossom. It lists a subset of the nodes.
  4.1989 +    /// Before using this iterator, you must allocate a 
  4.1990 +    /// MaxWeightedMatching class and execute it.
  4.1991 +    class BlossomIt {
  4.1992 +    public:
  4.1993 +
  4.1994 +      /// \brief Constructor.
  4.1995 +      ///
  4.1996 +      /// Constructor to get the nodes of the given variable.
  4.1997 +      ///
  4.1998 +      /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or 
  4.1999 +      /// \ref MaxWeightedMatching::start() "algorithm.start()" must be 
  4.2000 +      /// called before initializing this iterator.
  4.2001 +      BlossomIt(const MaxWeightedMatching& algorithm, int variable)
  4.2002 +        : _algorithm(&algorithm)
  4.2003 +      {
  4.2004 +        _index = _algorithm->_blossom_potential[variable].begin;
  4.2005 +        _last = _algorithm->_blossom_potential[variable].end;
  4.2006 +      }
  4.2007 +
  4.2008 +      /// \brief Conversion to \c Node.
  4.2009 +      ///
  4.2010 +      /// Conversion to \c Node.
  4.2011 +      operator Node() const {
  4.2012 +        return _algorithm->_blossom_node_list[_index];
  4.2013 +      }
  4.2014 +
  4.2015 +      /// \brief Increment operator.
  4.2016 +      ///
  4.2017 +      /// Increment operator.
  4.2018 +      BlossomIt& operator++() {
  4.2019 +        ++_index;
  4.2020 +        return *this;
  4.2021 +      }
  4.2022 +
  4.2023 +      /// \brief Validity checking
  4.2024 +      ///
  4.2025 +      /// Checks whether the iterator is invalid.
  4.2026 +      bool operator==(Invalid) const { return _index == _last; }
  4.2027 +
  4.2028 +      /// \brief Validity checking
  4.2029 +      ///
  4.2030 +      /// Checks whether the iterator is valid.
  4.2031 +      bool operator!=(Invalid) const { return _index != _last; }
  4.2032 +
  4.2033 +    private:
  4.2034 +      const MaxWeightedMatching* _algorithm;
  4.2035 +      int _last;
  4.2036 +      int _index;
  4.2037 +    };
  4.2038 +
  4.2039 +    /// @}
  4.2040 +
  4.2041 +  };
  4.2042 +
  4.2043 +  /// \ingroup matching
  4.2044 +  ///
  4.2045 +  /// \brief Weighted perfect matching in general graphs
  4.2046 +  ///
  4.2047 +  /// This class provides an efficient implementation of Edmond's
  4.2048 +  /// maximum weighted perfect matching algorithm. The implementation
  4.2049 +  /// is based on extensive use of priority queues and provides
  4.2050 +  /// \f$O(nm\log n)\f$ time complexity.
  4.2051 +  ///
  4.2052 +  /// The maximum weighted perfect matching problem is to find a subset of 
  4.2053 +  /// the edges in an undirected graph with maximum overall weight for which 
  4.2054 +  /// each node has exactly one incident edge.
  4.2055 +  /// It can be formulated with the following linear program.
  4.2056 +  /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
  4.2057 +  /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
  4.2058 +      \quad \forall B\in\mathcal{O}\f] */
  4.2059 +  /// \f[x_e \ge 0\quad \forall e\in E\f]
  4.2060 +  /// \f[\max \sum_{e\in E}x_ew_e\f]
  4.2061 +  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
  4.2062 +  /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
  4.2063 +  /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
  4.2064 +  /// subsets of the nodes.
  4.2065 +  ///
  4.2066 +  /// The algorithm calculates an optimal matching and a proof of the
  4.2067 +  /// optimality. The solution of the dual problem can be used to check
  4.2068 +  /// the result of the algorithm. The dual linear problem is the
  4.2069 +  /// following.
  4.2070 +  /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
  4.2071 +      w_{uv} \quad \forall uv\in E\f] */
  4.2072 +  /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
  4.2073 +  /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
  4.2074 +      \frac{\vert B \vert - 1}{2}z_B\f] */
  4.2075 +  ///
  4.2076 +  /// The algorithm can be executed with the run() function. 
  4.2077 +  /// After it the matching (the primal solution) and the dual solution
  4.2078 +  /// can be obtained using the query functions and the 
  4.2079 +  /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class, 
  4.2080 +  /// which is able to iterate on the nodes of a blossom. 
  4.2081 +  /// If the value type is integer, then the dual solution is multiplied
  4.2082 +  /// by \ref MaxWeightedMatching::dualScale "4".
  4.2083 +  ///
  4.2084 +  /// \tparam GR The undirected graph type the algorithm runs on.
  4.2085 +  /// \tparam WM The type edge weight map. The default type is 
  4.2086 +  /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
  4.2087 +#ifdef DOXYGEN
  4.2088 +  template <typename GR, typename WM>
  4.2089 +#else
  4.2090 +  template <typename GR,
  4.2091 +            typename WM = typename GR::template EdgeMap<int> >
  4.2092 +#endif
  4.2093 +  class MaxWeightedPerfectMatching {
  4.2094 +  public:
  4.2095 +
  4.2096 +    /// The graph type of the algorithm
  4.2097 +    typedef GR Graph;
  4.2098 +    /// The type of the edge weight map
  4.2099 +    typedef WM WeightMap;
  4.2100 +    /// The value type of the edge weights
  4.2101 +    typedef typename WeightMap::Value Value;
  4.2102 +
  4.2103 +    /// \brief Scaling factor for dual solution
  4.2104 +    ///
  4.2105 +    /// Scaling factor for dual solution, it is equal to 4 or 1
  4.2106 +    /// according to the value type.
  4.2107 +    static const int dualScale =
  4.2108 +      std::numeric_limits<Value>::is_integer ? 4 : 1;
  4.2109 +
  4.2110 +    /// The type of the matching map
  4.2111 +    typedef typename Graph::template NodeMap<typename Graph::Arc>
  4.2112 +    MatchingMap;
  4.2113 +
  4.2114 +  private:
  4.2115 +
  4.2116 +    TEMPLATE_GRAPH_TYPEDEFS(Graph);
  4.2117 +
  4.2118 +    typedef typename Graph::template NodeMap<Value> NodePotential;
  4.2119 +    typedef std::vector<Node> BlossomNodeList;
  4.2120 +
  4.2121 +    struct BlossomVariable {
  4.2122 +      int begin, end;
  4.2123 +      Value value;
  4.2124 +
  4.2125 +      BlossomVariable(int _begin, int _end, Value _value)
  4.2126 +        : begin(_begin), end(_end), value(_value) {}
  4.2127 +
  4.2128 +    };
  4.2129 +
  4.2130 +    typedef std::vector<BlossomVariable> BlossomPotential;
  4.2131 +
  4.2132 +    const Graph& _graph;
  4.2133 +    const WeightMap& _weight;
  4.2134 +
  4.2135 +    MatchingMap* _matching;
  4.2136 +
  4.2137 +    NodePotential* _node_potential;
  4.2138 +
  4.2139 +    BlossomPotential _blossom_potential;
  4.2140 +    BlossomNodeList _blossom_node_list;
  4.2141 +
  4.2142 +    int _node_num;
  4.2143 +    int _blossom_num;
  4.2144 +
  4.2145 +    typedef RangeMap<int> IntIntMap;
  4.2146 +
  4.2147 +    enum Status {
  4.2148 +      EVEN = -1, MATCHED = 0, ODD = 1
  4.2149 +    };
  4.2150 +
  4.2151 +    typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
  4.2152 +    struct BlossomData {
  4.2153 +      int tree;
  4.2154 +      Status status;
  4.2155 +      Arc pred, next;
  4.2156 +      Value pot, offset;
  4.2157 +    };
  4.2158 +
  4.2159 +    IntNodeMap *_blossom_index;
  4.2160 +    BlossomSet *_blossom_set;
  4.2161 +    RangeMap<BlossomData>* _blossom_data;
  4.2162 +
  4.2163 +    IntNodeMap *_node_index;
  4.2164 +    IntArcMap *_node_heap_index;
  4.2165 +
  4.2166 +    struct NodeData {
  4.2167 +
  4.2168 +      NodeData(IntArcMap& node_heap_index)
  4.2169 +        : heap(node_heap_index) {}
  4.2170 +
  4.2171 +      int blossom;
  4.2172 +      Value pot;
  4.2173 +      BinHeap<Value, IntArcMap> heap;
  4.2174 +      std::map<int, Arc> heap_index;
  4.2175 +
  4.2176 +      int tree;
  4.2177 +    };
  4.2178 +
  4.2179 +    RangeMap<NodeData>* _node_data;
  4.2180 +
  4.2181 +    typedef ExtendFindEnum<IntIntMap> TreeSet;
  4.2182 +
  4.2183 +    IntIntMap *_tree_set_index;
  4.2184 +    TreeSet *_tree_set;
  4.2185 +
  4.2186 +    IntIntMap *_delta2_index;
  4.2187 +    BinHeap<Value, IntIntMap> *_delta2;
  4.2188 +
  4.2189 +    IntEdgeMap *_delta3_index;
  4.2190 +    BinHeap<Value, IntEdgeMap> *_delta3;
  4.2191 +
  4.2192 +    IntIntMap *_delta4_index;
  4.2193 +    BinHeap<Value, IntIntMap> *_delta4;
  4.2194 +
  4.2195 +    Value _delta_sum;
  4.2196 +
  4.2197 +    void createStructures() {
  4.2198 +      _node_num = countNodes(_graph);
  4.2199 +      _blossom_num = _node_num * 3 / 2;
  4.2200 +
  4.2201 +      if (!_matching) {
  4.2202 +        _matching = new MatchingMap(_graph);
  4.2203 +      }
  4.2204 +      if (!_node_potential) {
  4.2205 +        _node_potential = new NodePotential(_graph);
  4.2206 +      }
  4.2207 +      if (!_blossom_set) {
  4.2208 +        _blossom_index = new IntNodeMap(_graph);
  4.2209 +        _blossom_set = new BlossomSet(*_blossom_index);
  4.2210 +        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
  4.2211 +      }
  4.2212 +
  4.2213 +      if (!_node_index) {
  4.2214 +        _node_index = new IntNodeMap(_graph);
  4.2215 +        _node_heap_index = new IntArcMap(_graph);
  4.2216 +        _node_data = new RangeMap<NodeData>(_node_num,
  4.2217 +                                            NodeData(*_node_heap_index));
  4.2218 +      }
  4.2219 +
  4.2220 +      if (!_tree_set) {
  4.2221 +        _tree_set_index = new IntIntMap(_blossom_num);
  4.2222 +        _tree_set = new TreeSet(*_tree_set_index);
  4.2223 +      }
  4.2224 +      if (!_delta2) {
  4.2225 +        _delta2_index = new IntIntMap(_blossom_num);
  4.2226 +        _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
  4.2227 +      }
  4.2228 +      if (!_delta3) {
  4.2229 +        _delta3_index = new IntEdgeMap(_graph);
  4.2230 +        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
  4.2231 +      }
  4.2232 +      if (!_delta4) {
  4.2233 +        _delta4_index = new IntIntMap(_blossom_num);
  4.2234 +        _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
  4.2235 +      }
  4.2236 +    }
  4.2237 +
  4.2238 +    void destroyStructures() {
  4.2239 +      _node_num = countNodes(_graph);
  4.2240 +      _blossom_num = _node_num * 3 / 2;
  4.2241 +
  4.2242 +      if (_matching) {
  4.2243 +        delete _matching;
  4.2244 +      }
  4.2245 +      if (_node_potential) {
  4.2246 +        delete _node_potential;
  4.2247 +      }
  4.2248 +      if (_blossom_set) {
  4.2249 +        delete _blossom_index;
  4.2250 +        delete _blossom_set;
  4.2251 +        delete _blossom_data;
  4.2252 +      }
  4.2253 +
  4.2254 +      if (_node_index) {
  4.2255 +        delete _node_index;
  4.2256 +        delete _node_heap_index;
  4.2257 +        delete _node_data;
  4.2258 +      }
  4.2259 +
  4.2260 +      if (_tree_set) {
  4.2261 +        delete _tree_set_index;
  4.2262 +        delete _tree_set;
  4.2263 +      }
  4.2264 +      if (_delta2) {
  4.2265 +        delete _delta2_index;
  4.2266 +        delete _delta2;
  4.2267 +      }
  4.2268 +      if (_delta3) {
  4.2269 +        delete _delta3_index;
  4.2270 +        delete _delta3;
  4.2271 +      }
  4.2272 +      if (_delta4) {
  4.2273 +        delete _delta4_index;
  4.2274 +        delete _delta4;
  4.2275 +      }
  4.2276 +    }
  4.2277 +
  4.2278 +    void matchedToEven(int blossom, int tree) {
  4.2279 +      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
  4.2280 +        _delta2->erase(blossom);
  4.2281 +      }
  4.2282 +
  4.2283 +      if (!_blossom_set->trivial(blossom)) {
  4.2284 +        (*_blossom_data)[blossom].pot -=
  4.2285 +          2 * (_delta_sum - (*_blossom_data)[blossom].offset);
  4.2286 +      }
  4.2287 +
  4.2288 +      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  4.2289 +           n != INVALID; ++n) {
  4.2290 +
  4.2291 +        _blossom_set->increase(n, std::numeric_limits<Value>::max());
  4.2292 +        int ni = (*_node_index)[n];
  4.2293 +
  4.2294 +        (*_node_data)[ni].heap.clear();
  4.2295 +        (*_node_data)[ni].heap_index.clear();
  4.2296 +
  4.2297 +        (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
  4.2298 +
  4.2299 +        for (InArcIt e(_graph, n); e != INVALID; ++e) {
  4.2300 +          Node v = _graph.source(e);
  4.2301 +          int vb = _blossom_set->find(v);
  4.2302 +          int vi = (*_node_index)[v];
  4.2303 +
  4.2304 +          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  4.2305 +            dualScale * _weight[e];
  4.2306 +
  4.2307 +          if ((*_blossom_data)[vb].status == EVEN) {
  4.2308 +            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
  4.2309 +              _delta3->push(e, rw / 2);
  4.2310 +            }
  4.2311 +          } else {
  4.2312 +            typename std::map<int, Arc>::iterator it =
  4.2313 +              (*_node_data)[vi].heap_index.find(tree);
  4.2314 +
  4.2315 +            if (it != (*_node_data)[vi].heap_index.end()) {
  4.2316 +              if ((*_node_data)[vi].heap[it->second] > rw) {
  4.2317 +                (*_node_data)[vi].heap.replace(it->second, e);
  4.2318 +                (*_node_data)[vi].heap.decrease(e, rw);
  4.2319 +                it->second = e;
  4.2320 +              }
  4.2321 +            } else {
  4.2322 +              (*_node_data)[vi].heap.push(e, rw);
  4.2323 +              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
  4.2324 +            }
  4.2325 +
  4.2326 +            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
  4.2327 +              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
  4.2328 +
  4.2329 +              if ((*_blossom_data)[vb].status == MATCHED) {
  4.2330 +                if (_delta2->state(vb) != _delta2->IN_HEAP) {
  4.2331 +                  _delta2->push(vb, _blossom_set->classPrio(vb) -
  4.2332 +                               (*_blossom_data)[vb].offset);
  4.2333 +                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
  4.2334 +                           (*_blossom_data)[vb].offset){
  4.2335 +                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
  4.2336 +                                   (*_blossom_data)[vb].offset);
  4.2337 +                }
  4.2338 +              }
  4.2339 +            }
  4.2340 +          }
  4.2341 +        }
  4.2342 +      }
  4.2343 +      (*_blossom_data)[blossom].offset = 0;
  4.2344 +    }
  4.2345 +
  4.2346 +    void matchedToOdd(int blossom) {
  4.2347 +      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
  4.2348 +        _delta2->erase(blossom);
  4.2349 +      }
  4.2350 +      (*_blossom_data)[blossom].offset += _delta_sum;
  4.2351 +      if (!_blossom_set->trivial(blossom)) {
  4.2352 +        _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
  4.2353 +                     (*_blossom_data)[blossom].offset);
  4.2354 +      }
  4.2355 +    }
  4.2356 +
  4.2357 +    void evenToMatched(int blossom, int tree) {
  4.2358 +      if (!_blossom_set->trivial(blossom)) {
  4.2359 +        (*_blossom_data)[blossom].pot += 2 * _delta_sum;
  4.2360 +      }
  4.2361 +
  4.2362 +      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  4.2363 +           n != INVALID; ++n) {
  4.2364 +        int ni = (*_node_index)[n];
  4.2365 +        (*_node_data)[ni].pot -= _delta_sum;
  4.2366 +
  4.2367 +        for (InArcIt e(_graph, n); e != INVALID; ++e) {
  4.2368 +          Node v = _graph.source(e);
  4.2369 +          int vb = _blossom_set->find(v);
  4.2370 +          int vi = (*_node_index)[v];
  4.2371 +
  4.2372 +          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  4.2373 +            dualScale * _weight[e];
  4.2374 +
  4.2375 +          if (vb == blossom) {
  4.2376 +            if (_delta3->state(e) == _delta3->IN_HEAP) {
  4.2377 +              _delta3->erase(e);
  4.2378 +            }
  4.2379 +          } else if ((*_blossom_data)[vb].status == EVEN) {
  4.2380 +
  4.2381 +            if (_delta3->state(e) == _delta3->IN_HEAP) {
  4.2382 +              _delta3->erase(e);
  4.2383 +            }
  4.2384 +
  4.2385 +            int vt = _tree_set->find(vb);
  4.2386 +
  4.2387 +            if (vt != tree) {
  4.2388 +
  4.2389 +              Arc r = _graph.oppositeArc(e);
  4.2390 +
  4.2391 +              typename std::map<int, Arc>::iterator it =
  4.2392 +                (*_node_data)[ni].heap_index.find(vt);
  4.2393 +
  4.2394 +              if (it != (*_node_data)[ni].heap_index.end()) {
  4.2395 +                if ((*_node_data)[ni].heap[it->second] > rw) {
  4.2396 +                  (*_node_data)[ni].heap.replace(it->second, r);
  4.2397 +                  (*_node_data)[ni].heap.decrease(r, rw);
  4.2398 +                  it->second = r;
  4.2399 +                }
  4.2400 +              } else {
  4.2401 +                (*_node_data)[ni].heap.push(r, rw);
  4.2402 +                (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
  4.2403 +              }
  4.2404 +
  4.2405 +              if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
  4.2406 +                _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
  4.2407 +
  4.2408 +                if (_delta2->state(blossom) != _delta2->IN_HEAP) {
  4.2409 +                  _delta2->push(blossom, _blossom_set->classPrio(blossom) -
  4.2410 +                               (*_blossom_data)[blossom].offset);
  4.2411 +                } else if ((*_delta2)[blossom] >
  4.2412 +                           _blossom_set->classPrio(blossom) -
  4.2413 +                           (*_blossom_data)[blossom].offset){
  4.2414 +                  _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
  4.2415 +                                   (*_blossom_data)[blossom].offset);
  4.2416 +                }
  4.2417 +              }
  4.2418 +            }
  4.2419 +          } else {
  4.2420 +
  4.2421 +            typename std::map<int, Arc>::iterator it =
  4.2422 +              (*_node_data)[vi].heap_index.find(tree);
  4.2423 +
  4.2424 +            if (it != (*_node_data)[vi].heap_index.end()) {
  4.2425 +              (*_node_data)[vi].heap.erase(it->second);
  4.2426 +              (*_node_data)[vi].heap_index.erase(it);
  4.2427 +              if ((*_node_data)[vi].heap.empty()) {
  4.2428 +                _blossom_set->increase(v, std::numeric_limits<Value>::max());
  4.2429 +              } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
  4.2430 +                _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
  4.2431 +              }
  4.2432 +
  4.2433 +              if ((*_blossom_data)[vb].status == MATCHED) {
  4.2434 +                if (_blossom_set->classPrio(vb) ==
  4.2435 +                    std::numeric_limits<Value>::max()) {
  4.2436 +                  _delta2->erase(vb);
  4.2437 +                } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
  4.2438 +                           (*_blossom_data)[vb].offset) {
  4.2439 +                  _delta2->increase(vb, _blossom_set->classPrio(vb) -
  4.2440 +                                   (*_blossom_data)[vb].offset);
  4.2441 +                }
  4.2442 +              }
  4.2443 +            }
  4.2444 +          }
  4.2445 +        }
  4.2446 +      }
  4.2447 +    }
  4.2448 +
  4.2449 +    void oddToMatched(int blossom) {
  4.2450 +      (*_blossom_data)[blossom].offset -= _delta_sum;
  4.2451 +
  4.2452 +      if (_blossom_set->classPrio(blossom) !=
  4.2453 +          std::numeric_limits<Value>::max()) {
  4.2454 +        _delta2->push(blossom, _blossom_set->classPrio(blossom) -
  4.2455 +                       (*_blossom_data)[blossom].offset);
  4.2456 +      }
  4.2457 +
  4.2458 +      if (!_blossom_set->trivial(blossom)) {
  4.2459 +        _delta4->erase(blossom);
  4.2460 +      }
  4.2461 +    }
  4.2462 +
  4.2463 +    void oddToEven(int blossom, int tree) {
  4.2464 +      if (!_blossom_set->trivial(blossom)) {
  4.2465 +        _delta4->erase(blossom);
  4.2466 +        (*_blossom_data)[blossom].pot -=
  4.2467 +          2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
  4.2468 +      }
  4.2469 +
  4.2470 +      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  4.2471 +           n != INVALID; ++n) {
  4.2472 +        int ni = (*_node_index)[n];
  4.2473 +
  4.2474 +        _blossom_set->increase(n, std::numeric_limits<Value>::max());
  4.2475 +
  4.2476 +        (*_node_data)[ni].heap.clear();
  4.2477 +        (*_node_data)[ni].heap_index.clear();
  4.2478 +        (*_node_data)[ni].pot +=
  4.2479 +          2 * _delta_sum - (*_blossom_data)[blossom].offset;
  4.2480 +
  4.2481 +        for (InArcIt e(_graph, n); e != INVALID; ++e) {
  4.2482 +          Node v = _graph.source(e);
  4.2483 +          int vb = _blossom_set->find(v);
  4.2484 +          int vi = (*_node_index)[v];
  4.2485 +
  4.2486 +          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  4.2487 +            dualScale * _weight[e];
  4.2488 +
  4.2489 +          if ((*_blossom_data)[vb].status == EVEN) {
  4.2490 +            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
  4.2491 +              _delta3->push(e, rw / 2);
  4.2492 +            }
  4.2493 +          } else {
  4.2494 +
  4.2495 +            typename std::map<int, Arc>::iterator it =
  4.2496 +              (*_node_data)[vi].heap_index.find(tree);
  4.2497 +
  4.2498 +            if (it != (*_node_data)[vi].heap_index.end()) {
  4.2499 +              if ((*_node_data)[vi].heap[it->second] > rw) {
  4.2500 +                (*_node_data)[vi].heap.replace(it->second, e);
  4.2501 +                (*_node_data)[vi].heap.decrease(e, rw);
  4.2502 +                it->second = e;
  4.2503 +              }
  4.2504 +            } else {
  4.2505 +              (*_node_data)[vi].heap.push(e, rw);
  4.2506 +              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
  4.2507 +            }
  4.2508 +
  4.2509 +            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
  4.2510 +              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
  4.2511 +
  4.2512 +              if ((*_blossom_data)[vb].status == MATCHED) {
  4.2513 +                if (_delta2->state(vb) != _delta2->IN_HEAP) {
  4.2514 +                  _delta2->push(vb, _blossom_set->classPrio(vb) -
  4.2515 +                               (*_blossom_data)[vb].offset);
  4.2516 +                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
  4.2517 +                           (*_blossom_data)[vb].offset) {
  4.2518 +                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
  4.2519 +                                   (*_blossom_data)[vb].offset);
  4.2520 +                }
  4.2521 +              }
  4.2522 +            }
  4.2523 +          }
  4.2524 +        }
  4.2525 +      }
  4.2526 +      (*_blossom_data)[blossom].offset = 0;
  4.2527 +    }
  4.2528 +
  4.2529 +    void alternatePath(int even, int tree) {
  4.2530 +      int odd;
  4.2531 +
  4.2532 +      evenToMatched(even, tree);
  4.2533 +      (*_blossom_data)[even].status = MATCHED;
  4.2534 +
  4.2535 +      while ((*_blossom_data)[even].pred != INVALID) {
  4.2536 +        odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
  4.2537 +        (*_blossom_data)[odd].status = MATCHED;
  4.2538 +        oddToMatched(odd);
  4.2539 +        (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
  4.2540 +
  4.2541 +        even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
  4.2542 +        (*_blossom_data)[even].status = MATCHED;
  4.2543 +        evenToMatched(even, tree);
  4.2544 +        (*_blossom_data)[even].next =
  4.2545 +          _graph.oppositeArc((*_blossom_data)[odd].pred);
  4.2546 +      }
  4.2547 +
  4.2548 +    }
  4.2549 +
  4.2550 +    void destroyTree(int tree) {
  4.2551 +      for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
  4.2552 +        if ((*_blossom_data)[b].status == EVEN) {
  4.2553 +          (*_blossom_data)[b].status = MATCHED;
  4.2554 +          evenToMatched(b, tree);
  4.2555 +        } else if ((*_blossom_data)[b].status == ODD) {
  4.2556 +          (*_blossom_data)[b].status = MATCHED;
  4.2557 +          oddToMatched(b);
  4.2558 +        }
  4.2559 +      }
  4.2560 +      _tree_set->eraseClass(tree);
  4.2561 +    }
  4.2562 +
  4.2563 +    void augmentOnEdge(const Edge& edge) {
  4.2564 +
  4.2565 +      int left = _blossom_set->find(_graph.u(edge));
  4.2566 +      int right = _blossom_set->find(_graph.v(edge));
  4.2567 +
  4.2568 +      int left_tree = _tree_set->find(left);
  4.2569 +      alternatePath(left, left_tree);
  4.2570 +      destroyTree(left_tree);
  4.2571 +
  4.2572 +      int right_tree = _tree_set->find(right);
  4.2573 +      alternatePath(right, right_tree);
  4.2574 +      destroyTree(right_tree);
  4.2575 +
  4.2576 +      (*_blossom_data)[left].next = _graph.direct(edge, true);
  4.2577 +      (*_blossom_data)[right].next = _graph.direct(edge, false);
  4.2578 +    }
  4.2579 +
  4.2580 +    void extendOnArc(const Arc& arc) {
  4.2581 +      int base = _blossom_set->find(_graph.target(arc));
  4.2582 +      int tree = _tree_set->find(base);
  4.2583 +
  4.2584 +      int odd = _blossom_set->find(_graph.source(arc));
  4.2585 +      _tree_set->insert(odd, tree);
  4.2586 +      (*_blossom_data)[odd].status = ODD;
  4.2587 +      matchedToOdd(odd);
  4.2588 +      (*_blossom_data)[odd].pred = arc;
  4.2589 +
  4.2590 +      int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
  4.2591 +      (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
  4.2592 +      _tree_set->insert(even, tree);
  4.2593 +      (*_blossom_data)[even].status = EVEN;
  4.2594 +      matchedToEven(even, tree);
  4.2595 +    }
  4.2596 +
  4.2597 +    void shrinkOnEdge(const Edge& edge, int tree) {
  4.2598 +      int nca = -1;
  4.2599 +      std::vector<int> left_path, right_path;
  4.2600 +
  4.2601 +      {
  4.2602 +        std::set<int> left_set, right_set;
  4.2603 +        int left = _blossom_set->find(_graph.u(edge));
  4.2604 +        left_path.push_back(left);
  4.2605 +        left_set.insert(left);
  4.2606 +
  4.2607 +        int right = _blossom_set->find(_graph.v(edge));
  4.2608 +        right_path.push_back(right);
  4.2609 +        right_set.insert(right);
  4.2610 +
  4.2611 +        while (true) {
  4.2612 +
  4.2613 +          if ((*_blossom_data)[left].pred == INVALID) break;
  4.2614 +
  4.2615 +          left =
  4.2616 +            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
  4.2617 +          left_path.push_back(left);
  4.2618 +          left =
  4.2619 +            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
  4.2620 +          left_path.push_back(left);
  4.2621 +
  4.2622 +          left_set.insert(left);
  4.2623 +
  4.2624 +          if (right_set.find(left) != right_set.end()) {
  4.2625 +            nca = left;
  4.2626 +            break;
  4.2627 +          }
  4.2628 +
  4.2629 +          if ((*_blossom_data)[right].pred == INVALID) break;
  4.2630 +
  4.2631 +          right =
  4.2632 +            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
  4.2633 +          right_path.push_back(right);
  4.2634 +          right =
  4.2635 +            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
  4.2636 +          right_path.push_back(right);
  4.2637 +
  4.2638 +          right_set.insert(right);
  4.2639 +
  4.2640 +          if (left_set.find(right) != left_set.end()) {
  4.2641 +            nca = right;
  4.2642 +            break;
  4.2643 +          }
  4.2644 +
  4.2645 +        }
  4.2646 +
  4.2647 +        if (nca == -1) {
  4.2648 +          if ((*_blossom_data)[left].pred == INVALID) {
  4.2649 +            nca = right;
  4.2650 +            while (left_set.find(nca) == left_set.end()) {
  4.2651 +              nca =
  4.2652 +                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  4.2653 +              right_path.push_back(nca);
  4.2654 +              nca =
  4.2655 +                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  4.2656 +              right_path.push_back(nca);
  4.2657 +            }
  4.2658 +          } else {
  4.2659 +            nca = left;
  4.2660 +            while (right_set.find(nca) == right_set.end()) {
  4.2661 +              nca =
  4.2662 +                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  4.2663 +              left_path.push_back(nca);
  4.2664 +              nca =
  4.2665 +                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  4.2666 +              left_path.push_back(nca);
  4.2667 +            }
  4.2668 +          }
  4.2669 +        }
  4.2670 +      }
  4.2671 +
  4.2672 +      std::vector<int> subblossoms;
  4.2673 +      Arc prev;
  4.2674 +
  4.2675 +      prev = _graph.direct(edge, true);
  4.2676 +      for (int i = 0; left_path[i] != nca; i += 2) {
  4.2677 +        subblossoms.push_back(left_path[i]);
  4.2678 +        (*_blossom_data)[left_path[i]].next = prev;
  4.2679 +        _tree_set->erase(left_path[i]);
  4.2680 +
  4.2681 +        subblossoms.push_back(left_path[i + 1]);
  4.2682 +        (*_blossom_data)[left_path[i + 1]].status = EVEN;
  4.2683 +        oddToEven(left_path[i + 1], tree);
  4.2684 +        _tree_set->erase(left_path[i + 1]);
  4.2685 +        prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
  4.2686 +      }
  4.2687 +
  4.2688 +      int k = 0;
  4.2689 +      while (right_path[k] != nca) ++k;
  4.2690 +
  4.2691 +      subblossoms.push_back(nca);
  4.2692 +      (*_blossom_data)[nca].next = prev;
  4.2693 +
  4.2694 +      for (int i = k - 2; i >= 0; i -= 2) {
  4.2695 +        subblossoms.push_back(right_path[i + 1]);
  4.2696 +        (*_blossom_data)[right_path[i + 1]].status = EVEN;
  4.2697 +        oddToEven(right_path[i + 1], tree);
  4.2698 +        _tree_set->erase(right_path[i + 1]);
  4.2699 +
  4.2700 +        (*_blossom_data)[right_path[i + 1]].next =
  4.2701 +          (*_blossom_data)[right_path[i + 1]].pred;
  4.2702 +
  4.2703 +        subblossoms.push_back(right_path[i]);
  4.2704 +        _tree_set->erase(right_path[i]);
  4.2705 +      }
  4.2706 +
  4.2707 +      int surface =
  4.2708 +        _blossom_set->join(subblossoms.begin(), subblossoms.end());
  4.2709 +
  4.2710 +      for (int i = 0; i < int(subblossoms.size()); ++i) {
  4.2711 +        if (!_blossom_set->trivial(subblossoms[i])) {
  4.2712 +          (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
  4.2713 +        }
  4.2714 +        (*_blossom_data)[subblossoms[i]].status = MATCHED;
  4.2715 +      }
  4.2716 +
  4.2717 +      (*_blossom_data)[surface].pot = -2 * _delta_sum;
  4.2718 +      (*_blossom_data)[surface].offset = 0;
  4.2719 +      (*_blossom_data)[surface].status = EVEN;
  4.2720 +      (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
  4.2721 +      (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
  4.2722 +
  4.2723 +      _tree_set->insert(surface, tree);
  4.2724 +      _tree_set->erase(nca);
  4.2725 +    }
  4.2726 +
  4.2727 +    void splitBlossom(int blossom) {
  4.2728 +      Arc next = (*_blossom_data)[blossom].next;
  4.2729 +      Arc pred = (*_blossom_data)[blossom].pred;
  4.2730 +
  4.2731 +      int tree = _tree_set->find(blossom);
  4.2732 +
  4.2733 +      (*_blossom_data)[blossom].status = MATCHED;
  4.2734 +      oddToMatched(blossom);
  4.2735 +      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
  4.2736 +        _delta2->erase(blossom);
  4.2737 +      }
  4.2738 +
  4.2739 +      std::vector<int> subblossoms;
  4.2740 +      _blossom_set->split(blossom, std::back_inserter(subblossoms));
  4.2741 +
  4.2742 +      Value offset = (*_blossom_data)[blossom].offset;
  4.2743 +      int b = _blossom_set->find(_graph.source(pred));
  4.2744 +      int d = _blossom_set->find(_graph.source(next));
  4.2745 +
  4.2746 +      int ib = -1, id = -1;
  4.2747 +      for (int i = 0; i < int(subblossoms.size()); ++i) {
  4.2748 +        if (subblossoms[i] == b) ib = i;
  4.2749 +        if (subblossoms[i] == d) id = i;
  4.2750 +
  4.2751 +        (*_blossom_data)[subblossoms[i]].offset = offset;
  4.2752 +        if (!_blossom_set->trivial(subblossoms[i])) {
  4.2753 +          (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
  4.2754 +        }
  4.2755 +        if (_blossom_set->classPrio(subblossoms[i]) !=
  4.2756 +            std::numeric_limits<Value>::max()) {
  4.2757 +          _delta2->push(subblossoms[i],
  4.2758 +                        _blossom_set->classPrio(subblossoms[i]) -
  4.2759 +                        (*_blossom_data)[subblossoms[i]].offset);
  4.2760 +        }
  4.2761 +      }
  4.2762 +
  4.2763 +      if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
  4.2764 +        for (int i = (id + 1) % subblossoms.size();
  4.2765 +             i != ib; i = (i + 2) % subblossoms.size()) {
  4.2766 +          int sb = subblossoms[i];
  4.2767 +          int tb = subblossoms[(i + 1) % subblossoms.size()];
  4.2768 +          (*_blossom_data)[sb].next =
  4.2769 +            _graph.oppositeArc((*_blossom_data)[tb].next);
  4.2770 +        }
  4.2771 +
  4.2772 +        for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
  4.2773 +          int sb = subblossoms[i];
  4.2774 +          int tb = subblossoms[(i + 1) % subblossoms.size()];
  4.2775 +          int ub = subblossoms[(i + 2) % subblossoms.size()];
  4.2776 +
  4.2777 +          (*_blossom_data)[sb].status = ODD;
  4.2778 +          matchedToOdd(sb);
  4.2779 +          _tree_set->insert(sb, tree);
  4.2780 +          (*_blossom_data)[sb].pred = pred;
  4.2781 +          (*_blossom_data)[sb].next =
  4.2782 +                           _graph.oppositeArc((*_blossom_data)[tb].next);
  4.2783 +
  4.2784 +          pred = (*_blossom_data)[ub].next;
  4.2785 +
  4.2786 +          (*_blossom_data)[tb].status = EVEN;
  4.2787 +          matchedToEven(tb, tree);
  4.2788 +          _tree_set->insert(tb, tree);
  4.2789 +          (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
  4.2790 +        }
  4.2791 +
  4.2792 +        (*_blossom_data)[subblossoms[id]].status = ODD;
  4.2793 +        matchedToOdd(subblossoms[id]);
  4.2794 +        _tree_set->insert(subblossoms[id], tree);
  4.2795 +        (*_blossom_data)[subblossoms[id]].next = next;
  4.2796 +        (*_blossom_data)[subblossoms[id]].pred = pred;
  4.2797 +
  4.2798 +      } else {
  4.2799 +
  4.2800 +        for (int i = (ib + 1) % subblossoms.size();
  4.2801 +             i != id; i = (i + 2) % subblossoms.size()) {
  4.2802 +          int sb = subblossoms[i];
  4.2803 +          int tb = subblossoms[(i + 1) % subblossoms.size()];
  4.2804 +          (*_blossom_data)[sb].next =
  4.2805 +            _graph.oppositeArc((*_blossom_data)[tb].next);
  4.2806 +        }
  4.2807 +
  4.2808 +        for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
  4.2809 +          int sb = subblossoms[i];
  4.2810 +          int tb = subblossoms[(i + 1) % subblossoms.size()];
  4.2811 +          int ub = subblossoms[(i + 2) % subblossoms.size()];
  4.2812 +
  4.2813 +          (*_blossom_data)[sb].status = ODD;
  4.2814 +          matchedToOdd(sb);
  4.2815 +          _tree_set->insert(sb, tree);
  4.2816 +          (*_blossom_data)[sb].next = next;
  4.2817 +          (*_blossom_data)[sb].pred =
  4.2818 +            _graph.oppositeArc((*_blossom_data)[tb].next);
  4.2819 +
  4.2820 +          (*_blossom_data)[tb].status = EVEN;
  4.2821 +          matchedToEven(tb, tree);
  4.2822 +          _tree_set->insert(tb, tree);
  4.2823 +          (*_blossom_data)[tb].pred =
  4.2824 +            (*_blossom_data)[tb].next =
  4.2825 +            _graph.oppositeArc((*_blossom_data)[ub].next);
  4.2826 +          next = (*_blossom_data)[ub].next;
  4.2827 +        }
  4.2828 +
  4.2829 +        (*_blossom_data)[subblossoms[ib]].status = ODD;
  4.2830 +        matchedToOdd(subblossoms[ib]);
  4.2831 +        _tree_set->insert(subblossoms[ib], tree);
  4.2832 +        (*_blossom_data)[subblossoms[ib]].next = next;
  4.2833 +        (*_blossom_data)[subblossoms[ib]].pred = pred;
  4.2834 +      }
  4.2835 +      _tree_set->erase(blossom);
  4.2836 +    }
  4.2837 +
  4.2838 +    void extractBlossom(int blossom, const Node& base, const Arc& matching) {
  4.2839 +      if (_blossom_set->trivial(blossom)) {
  4.2840 +        int bi = (*_node_index)[base];
  4.2841 +        Value pot = (*_node_data)[bi].pot;
  4.2842 +
  4.2843 +        (*_matching)[base] = matching;
  4.2844 +        _blossom_node_list.push_back(base);
  4.2845 +        (*_node_potential)[base] = pot;
  4.2846 +      } else {
  4.2847 +
  4.2848 +        Value pot = (*_blossom_data)[blossom].pot;
  4.2849 +        int bn = _blossom_node_list.size();
  4.2850 +
  4.2851 +        std::vector<int> subblossoms;
  4.2852 +        _blossom_set->split(blossom, std::back_inserter(subblossoms));
  4.2853 +        int b = _blossom_set->find(base);
  4.2854 +        int ib = -1;
  4.2855 +        for (int i = 0; i < int(subblossoms.size()); ++i) {
  4.2856 +          if (subblossoms[i] == b) { ib = i; break; }
  4.2857 +        }
  4.2858 +
  4.2859 +        for (int i = 1; i < int(subblossoms.size()); i += 2) {
  4.2860 +          int sb = subblossoms[(ib + i) % subblossoms.size()];
  4.2861 +          int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
  4.2862 +
  4.2863 +          Arc m = (*_blossom_data)[tb].next;
  4.2864 +          extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
  4.2865 +          extractBlossom(tb, _graph.source(m), m);
  4.2866 +        }
  4.2867 +        extractBlossom(subblossoms[ib], base, matching);
  4.2868 +
  4.2869 +        int en = _blossom_node_list.size();
  4.2870 +
  4.2871 +        _blossom_potential.push_back(BlossomVariable(bn, en, pot));
  4.2872 +      }
  4.2873 +    }
  4.2874 +
  4.2875 +    void extractMatching() {
  4.2876 +      std::vector<int> blossoms;
  4.2877 +      for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
  4.2878 +        blossoms.push_back(c);
  4.2879 +      }
  4.2880 +
  4.2881 +      for (int i = 0; i < int(blossoms.size()); ++i) {
  4.2882 +
  4.2883 +        Value offset = (*_blossom_data)[blossoms[i]].offset;
  4.2884 +        (*_blossom_data)[blossoms[i]].pot += 2 * offset;
  4.2885 +        for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
  4.2886 +             n != INVALID; ++n) {
  4.2887 +          (*_node_data)[(*_node_index)[n]].pot -= offset;
  4.2888 +        }
  4.2889 +
  4.2890 +        Arc matching = (*_blossom_data)[blossoms[i]].next;
  4.2891 +        Node base = _graph.source(matching);
  4.2892 +        extractBlossom(blossoms[i], base, matching);
  4.2893 +      }
  4.2894 +    }
  4.2895 +
  4.2896 +  public:
  4.2897 +
  4.2898 +    /// \brief Constructor
  4.2899 +    ///
  4.2900 +    /// Constructor.
  4.2901 +    MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
  4.2902 +      : _graph(graph), _weight(weight), _matching(0),
  4.2903 +        _node_potential(0), _blossom_potential(), _blossom_node_list(),
  4.2904 +        _node_num(0), _blossom_num(0),
  4.2905 +
  4.2906 +        _blossom_index(0), _blossom_set(0), _blossom_data(0),
  4.2907 +        _node_index(0), _node_heap_index(0), _node_data(0),
  4.2908 +        _tree_set_index(0), _tree_set(0),
  4.2909 +
  4.2910 +        _delta2_index(0), _delta2(0),
  4.2911 +        _delta3_index(0), _delta3(0),
  4.2912 +        _delta4_index(0), _delta4(0),
  4.2913 +
  4.2914 +        _delta_sum() {}
  4.2915 +
  4.2916 +    ~MaxWeightedPerfectMatching() {
  4.2917 +      destroyStructures();
  4.2918 +    }
  4.2919 +
  4.2920 +    /// \name Execution Control
  4.2921 +    /// The simplest way to execute the algorithm is to use the
  4.2922 +    /// \ref run() member function.
  4.2923 +
  4.2924 +    ///@{
  4.2925 +
  4.2926 +    /// \brief Initialize the algorithm
  4.2927 +    ///
  4.2928 +    /// This function initializes the algorithm.
  4.2929 +    void init() {
  4.2930 +      createStructures();
  4.2931 +
  4.2932 +      for (ArcIt e(_graph); e != INVALID; ++e) {
  4.2933 +        (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
  4.2934 +      }
  4.2935 +      for (EdgeIt e(_graph); e != INVALID; ++e) {
  4.2936 +        (*_delta3_index)[e] = _delta3->PRE_HEAP;
  4.2937 +      }
  4.2938 +      for (int i = 0; i < _blossom_num; ++i) {
  4.2939 +        (*_delta2_index)[i] = _delta2->PRE_HEAP;
  4.2940 +        (*_delta4_index)[i] = _delta4->PRE_HEAP;
  4.2941 +      }
  4.2942 +
  4.2943 +      int index = 0;
  4.2944 +      for (NodeIt n(_graph); n != INVALID; ++n) {
  4.2945 +        Value max = - std::numeric_limits<Value>::max();
  4.2946 +        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
  4.2947 +          if (_graph.target(e) == n) continue;
  4.2948 +          if ((dualScale * _weight[e]) / 2 > max) {
  4.2949 +            max = (dualScale * _weight[e]) / 2;
  4.2950 +          }
  4.2951 +        }
  4.2952 +        (*_node_index)[n] = index;
  4.2953 +        (*_node_data)[index].pot = max;
  4.2954 +        int blossom =
  4.2955 +          _blossom_set->insert(n, std::numeric_limits<Value>::max());
  4.2956 +
  4.2957 +        _tree_set->insert(blossom);
  4.2958 +
  4.2959 +        (*_blossom_data)[blossom].status = EVEN;
  4.2960 +        (*_blossom_data)[blossom].pred = INVALID;
  4.2961 +        (*_blossom_data)[blossom].next = INVALID;
  4.2962 +        (*_blossom_data)[blossom].pot = 0;
  4.2963 +        (*_blossom_data)[blossom].offset = 0;
  4.2964 +        ++index;
  4.2965 +      }
  4.2966 +      for (EdgeIt e(_graph); e != INVALID; ++e) {
  4.2967 +        int si = (*_node_index)[_graph.u(e)];
  4.2968 +        int ti = (*_node_index)[_graph.v(e)];
  4.2969 +        if (_graph.u(e) != _graph.v(e)) {
  4.2970 +          _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
  4.2971 +                            dualScale * _weight[e]) / 2);
  4.2972 +        }
  4.2973 +      }
  4.2974 +    }
  4.2975 +
  4.2976 +    /// \brief Start the algorithm
  4.2977 +    ///
  4.2978 +    /// This function starts the algorithm.
  4.2979 +    ///
  4.2980 +    /// \pre \ref init() must be called before using this function.
  4.2981 +    bool start() {
  4.2982 +      enum OpType {
  4.2983 +        D2, D3, D4
  4.2984 +      };
  4.2985 +
  4.2986 +      int unmatched = _node_num;
  4.2987 +      while (unmatched > 0) {
  4.2988 +        Value d2 = !_delta2->empty() ?
  4.2989 +          _delta2->prio() : std::numeric_limits<Value>::max();
  4.2990 +
  4.2991 +        Value d3 = !_delta3->empty() ?
  4.2992 +          _delta3->prio() : std::numeric_limits<Value>::max();
  4.2993 +
  4.2994 +        Value d4 = !_delta4->empty() ?
  4.2995 +          _delta4->prio() : std::numeric_limits<Value>::max();
  4.2996 +
  4.2997 +        _delta_sum = d2; OpType ot = D2;
  4.2998 +        if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
  4.2999 +        if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
  4.3000 +
  4.3001 +        if (_delta_sum == std::numeric_limits<Value>::max()) {
  4.3002 +          return false;
  4.3003 +        }
  4.3004 +
  4.3005 +        switch (ot) {
  4.3006 +        case D2:
  4.3007 +          {
  4.3008 +            int blossom = _delta2->top();
  4.3009 +            Node n = _blossom_set->classTop(blossom);
  4.3010 +            Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
  4.3011 +            extendOnArc(e);
  4.3012 +          }
  4.3013 +          break;
  4.3014 +        case D3:
  4.3015 +          {
  4.3016 +            Edge e = _delta3->top();
  4.3017 +
  4.3018 +            int left_blossom = _blossom_set->find(_graph.u(e));
  4.3019 +            int right_blossom = _blossom_set->find(_graph.v(e));
  4.3020 +
  4.3021 +            if (left_blossom == right_blossom) {
  4.3022 +              _delta3->pop();
  4.3023 +            } else {
  4.3024 +              int left_tree = _tree_set->find(left_blossom);
  4.3025 +              int right_tree = _tree_set->find(right_blossom);
  4.3026 +
  4.3027 +              if (left_tree == right_tree) {
  4.3028 +                shrinkOnEdge(e, left_tree);
  4.3029 +              } else {
  4.3030 +                augmentOnEdge(e);
  4.3031 +                unmatched -= 2;
  4.3032 +              }
  4.3033 +            }
  4.3034 +          } break;
  4.3035 +        case D4:
  4.3036 +          splitBlossom(_delta4->top());
  4.3037 +          break;
  4.3038 +        }
  4.3039 +      }
  4.3040 +      extractMatching();
  4.3041 +      return true;
  4.3042 +    }
  4.3043 +
  4.3044 +    /// \brief Run the algorithm.
  4.3045 +    ///
  4.3046 +    /// This method runs the \c %MaxWeightedPerfectMatching algorithm.
  4.3047 +    ///
  4.3048 +    /// \note mwpm.run() is just a shortcut of the following code.
  4.3049 +    /// \code
  4.3050 +    ///   mwpm.init();
  4.3051 +    ///   mwpm.start();
  4.3052 +    /// \endcode
  4.3053 +    bool run() {
  4.3054 +      init();
  4.3055 +      return start();
  4.3056 +    }
  4.3057 +
  4.3058 +    /// @}
  4.3059 +
  4.3060 +    /// \name Primal Solution
  4.3061 +    /// Functions to get the primal solution, i.e. the maximum weighted 
  4.3062 +    /// perfect matching.\n
  4.3063 +    /// Either \ref run() or \ref start() function should be called before
  4.3064 +    /// using them.
  4.3065 +
  4.3066 +    /// @{
  4.3067 +
  4.3068 +    /// \brief Return the weight of the matching.
  4.3069 +    ///
  4.3070 +    /// This function returns the weight of the found matching.
  4.3071 +    ///
  4.3072 +    /// \pre Either run() or start() must be called before using this function.
  4.3073 +    Value matchingWeight() const {
  4.3074 +      Value sum = 0;
  4.3075 +      for (NodeIt n(_graph); n != INVALID; ++n) {
  4.3076 +        if ((*_matching)[n] != INVALID) {
  4.3077 +          sum += _weight[(*_matching)[n]];
  4.3078 +        }
  4.3079 +      }
  4.3080 +      return sum /= 2;
  4.3081 +    }
  4.3082 +
  4.3083 +    /// \brief Return \c true if the given edge is in the matching.
  4.3084 +    ///
  4.3085 +    /// This function returns \c true if the given edge is in the found 
  4.3086 +    /// matching.
  4.3087 +    ///
  4.3088 +    /// \pre Either run() or start() must be called before using this function.
  4.3089 +    bool matching(const Edge& edge) const {
  4.3090 +      return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
  4.3091 +    }
  4.3092 +
  4.3093 +    /// \brief Return the matching arc (or edge) incident to the given node.
  4.3094 +    ///
  4.3095 +    /// This function returns the matching arc (or edge) incident to the
  4.3096 +    /// given node in the found matching or \c INVALID if the node is 
  4.3097 +    /// not covered by the matching.
  4.3098 +    ///
  4.3099 +    /// \pre Either run() or start() must be called before using this function.
  4.3100 +    Arc matching(const Node& node) const {
  4.3101 +      return (*_matching)[node];
  4.3102 +    }
  4.3103 +
  4.3104 +    /// \brief Return a const reference to the matching map.
  4.3105 +    ///
  4.3106 +    /// This function returns a const reference to a node map that stores
  4.3107 +    /// the matching arc (or edge) incident to each node.
  4.3108 +    const MatchingMap& matchingMap() const {
  4.3109 +      return *_matching;
  4.3110 +    }
  4.3111 +
  4.3112 +    /// \brief Return the mate of the given node.
  4.3113 +    ///
  4.3114 +    /// This function returns the mate of the given node in the found 
  4.3115 +    /// matching or \c INVALID if the node is not covered by the matching.
  4.3116 +    ///
  4.3117 +    /// \pre Either run() or start() must be called before using this function.
  4.3118 +    Node mate(const Node& node) const {
  4.3119 +      return _graph.target((*_matching)[node]);
  4.3120 +    }
  4.3121 +
  4.3122 +    /// @}
  4.3123 +
  4.3124 +    /// \name Dual Solution
  4.3125 +    /// Functions to get the dual solution.\n
  4.3126 +    /// Either \ref run() or \ref start() function should be called before
  4.3127 +    /// using them.
  4.3128 +
  4.3129 +    /// @{
  4.3130 +
  4.3131 +    /// \brief Return the value of the dual solution.
  4.3132 +    ///
  4.3133 +    /// This function returns the value of the dual solution. 
  4.3134 +    /// It should be equal to the primal value scaled by \ref dualScale 
  4.3135 +    /// "dual scale".
  4.3136 +    ///
  4.3137 +    /// \pre Either run() or start() must be called before using this function.
  4.3138 +    Value dualValue() const {
  4.3139 +      Value sum = 0;
  4.3140 +      for (NodeIt n(_graph); n != INVALID; ++n) {
  4.3141 +        sum += nodeValue(n);
  4.3142 +      }
  4.3143 +      for (int i = 0; i < blossomNum(); ++i) {
  4.3144 +        sum += blossomValue(i) * (blossomSize(i) / 2);
  4.3145 +      }
  4.3146 +      return sum;
  4.3147 +    }
  4.3148 +
  4.3149 +    /// \brief Return the dual value (potential) of the given node.
  4.3150 +    ///
  4.3151 +    /// This function returns the dual value (potential) of the given node.
  4.3152 +    ///
  4.3153 +    /// \pre Either run() or start() must be called before using this function.
  4.3154 +    Value nodeValue(const Node& n) const {
  4.3155 +      return (*_node_potential)[n];
  4.3156 +    }
  4.3157 +
  4.3158 +    /// \brief Return the number of the blossoms in the basis.
  4.3159 +    ///
  4.3160 +    /// This function returns the number of the blossoms in the basis.
  4.3161 +    ///
  4.3162 +    /// \pre Either run() or start() must be called before using this function.
  4.3163 +    /// \see BlossomIt
  4.3164 +    int blossomNum() const {
  4.3165 +      return _blossom_potential.size();
  4.3166 +    }
  4.3167 +
  4.3168 +    /// \brief Return the number of the nodes in the given blossom.
  4.3169 +    ///
  4.3170 +    /// This function returns the number of the nodes in the given blossom.
  4.3171 +    ///
  4.3172 +    /// \pre Either run() or start() must be called before using this function.
  4.3173 +    /// \see BlossomIt
  4.3174 +    int blossomSize(int k) const {
  4.3175 +      return _blossom_potential[k].end - _blossom_potential[k].begin;
  4.3176 +    }
  4.3177 +
  4.3178 +    /// \brief Return the dual value (ptential) of the given blossom.
  4.3179 +    ///
  4.3180 +    /// This function returns the dual value (ptential) of the given blossom.
  4.3181 +    ///
  4.3182 +    /// \pre Either run() or start() must be called before using this function.
  4.3183 +    Value blossomValue(int k) const {
  4.3184 +      return _blossom_potential[k].value;
  4.3185 +    }
  4.3186 +
  4.3187 +    /// \brief Iterator for obtaining the nodes of a blossom.
  4.3188 +    ///
  4.3189 +    /// This class provides an iterator for obtaining the nodes of the 
  4.3190 +    /// given blossom. It lists a subset of the nodes.
  4.3191 +    /// Before using this iterator, you must allocate a 
  4.3192 +    /// MaxWeightedPerfectMatching class and execute it.
  4.3193 +    class BlossomIt {
  4.3194 +    public:
  4.3195 +
  4.3196 +      /// \brief Constructor.
  4.3197 +      ///
  4.3198 +      /// Constructor to get the nodes of the given variable.
  4.3199 +      ///
  4.3200 +      /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()" 
  4.3201 +      /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()" 
  4.3202 +      /// must be called before initializing this iterator.
  4.3203 +      BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
  4.3204 +        : _algorithm(&algorithm)
  4.3205 +      {
  4.3206 +        _index = _algorithm->_blossom_potential[variable].begin;
  4.3207 +        _last = _algorithm->_blossom_potential[variable].end;
  4.3208 +      }
  4.3209 +
  4.3210 +      /// \brief Conversion to \c Node.
  4.3211 +      ///
  4.3212 +      /// Conversion to \c Node.
  4.3213 +      operator Node() const {
  4.3214 +        return _algorithm->_blossom_node_list[_index];
  4.3215 +      }
  4.3216 +
  4.3217 +      /// \brief Increment operator.
  4.3218 +      ///
  4.3219 +      /// Increment operator.
  4.3220 +      BlossomIt& operator++() {
  4.3221 +        ++_index;
  4.3222 +        return *this;
  4.3223 +      }
  4.3224 +
  4.3225 +      /// \brief Validity checking
  4.3226 +      ///
  4.3227 +      /// This function checks whether the iterator is invalid.
  4.3228 +      bool operator==(Invalid) const { return _index == _last; }
  4.3229 +
  4.3230 +      /// \brief Validity checking
  4.3231 +      ///
  4.3232 +      /// This function checks whether the iterator is valid.
  4.3233 +      bool operator!=(Invalid) const { return _index != _last; }
  4.3234 +
  4.3235 +    private:
  4.3236 +      const MaxWeightedPerfectMatching* _algorithm;
  4.3237 +      int _last;
  4.3238 +      int _index;
  4.3239 +    };
  4.3240 +
  4.3241 +    /// @}
  4.3242 +
  4.3243 +  };
  4.3244 +
  4.3245 +} //END OF NAMESPACE LEMON
  4.3246 +
  4.3247 +#endif //LEMON_MAX_MATCHING_H
     5.1 --- a/lemon/max_matching.h	Tue Apr 21 10:34:49 2009 +0100
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,3107 +0,0 @@
     5.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
     5.5 - *
     5.6 - * This file is a part of LEMON, a generic C++ optimization library.
     5.7 - *
     5.8 - * Copyright (C) 2003-2009
     5.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
    5.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
    5.11 - *
    5.12 - * Permission to use, modify and distribute this software is granted
    5.13 - * provided that this copyright notice appears in all copies. For
    5.14 - * precise terms see the accompanying LICENSE file.
    5.15 - *
    5.16 - * This software is provided "AS IS" with no warranty of any kind,
    5.17 - * express or implied, and with no claim as to its suitability for any
    5.18 - * purpose.
    5.19 - *
    5.20 - */
    5.21 -
    5.22 -#ifndef LEMON_MAX_MATCHING_H
    5.23 -#define LEMON_MAX_MATCHING_H
    5.24 -
    5.25 -#include <vector>
    5.26 -#include <queue>
    5.27 -#include <set>
    5.28 -#include <limits>
    5.29 -
    5.30 -#include <lemon/core.h>
    5.31 -#include <lemon/unionfind.h>
    5.32 -#include <lemon/bin_heap.h>
    5.33 -#include <lemon/maps.h>
    5.34 -
    5.35 -///\ingroup matching
    5.36 -///\file
    5.37 -///\brief Maximum matching algorithms in general graphs.
    5.38 -
    5.39 -namespace lemon {
    5.40 -
    5.41 -  /// \ingroup matching
    5.42 -  ///
    5.43 -  /// \brief Edmonds' alternating forest maximum matching algorithm.
    5.44 -  ///
    5.45 -  /// This class implements Edmonds' alternating forest matching
    5.46 -  /// algorithm. The algorithm can be started from an arbitrary initial
    5.47 -  /// matching (the default is the empty one)
    5.48 -  ///
    5.49 -  /// The dual solution of the problem is a map of the nodes to
    5.50 -  /// MaxMatching::Status, having values \c EVEN/D, \c ODD/A and \c
    5.51 -  /// MATCHED/C showing the Gallai-Edmonds decomposition of the
    5.52 -  /// graph. The nodes in \c EVEN/D induce a graph with
    5.53 -  /// factor-critical components, the nodes in \c ODD/A form the
    5.54 -  /// barrier, and the nodes in \c MATCHED/C induce a graph having a
    5.55 -  /// perfect matching. The number of the factor-critical components
    5.56 -  /// minus the number of barrier nodes is a lower bound on the
    5.57 -  /// unmatched nodes, and the matching is optimal if and only if this bound is
    5.58 -  /// tight. This decomposition can be attained by calling \c
    5.59 -  /// decomposition() after running the algorithm.
    5.60 -  ///
    5.61 -  /// \param GR The graph type the algorithm runs on.
    5.62 -  template <typename GR>
    5.63 -  class MaxMatching {
    5.64 -  public:
    5.65 -
    5.66 -    typedef GR Graph;
    5.67 -    typedef typename Graph::template NodeMap<typename Graph::Arc>
    5.68 -    MatchingMap;
    5.69 -
    5.70 -    ///\brief Indicates the Gallai-Edmonds decomposition of the graph.
    5.71 -    ///
    5.72 -    ///Indicates the Gallai-Edmonds decomposition of the graph. The
    5.73 -    ///nodes with Status \c EVEN/D induce a graph with factor-critical
    5.74 -    ///components, the nodes in \c ODD/A form the canonical barrier,
    5.75 -    ///and the nodes in \c MATCHED/C induce a graph having a perfect
    5.76 -    ///matching.
    5.77 -    enum Status {
    5.78 -      EVEN = 1, D = 1, MATCHED = 0, C = 0, ODD = -1, A = -1, UNMATCHED = -2
    5.79 -    };
    5.80 -
    5.81 -    typedef typename Graph::template NodeMap<Status> StatusMap;
    5.82 -
    5.83 -  private:
    5.84 -
    5.85 -    TEMPLATE_GRAPH_TYPEDEFS(Graph);
    5.86 -
    5.87 -    typedef UnionFindEnum<IntNodeMap> BlossomSet;
    5.88 -    typedef ExtendFindEnum<IntNodeMap> TreeSet;
    5.89 -    typedef RangeMap<Node> NodeIntMap;
    5.90 -    typedef MatchingMap EarMap;
    5.91 -    typedef std::vector<Node> NodeQueue;
    5.92 -
    5.93 -    const Graph& _graph;
    5.94 -    MatchingMap* _matching;
    5.95 -    StatusMap* _status;
    5.96 -
    5.97 -    EarMap* _ear;
    5.98 -
    5.99 -    IntNodeMap* _blossom_set_index;
   5.100 -    BlossomSet* _blossom_set;
   5.101 -    NodeIntMap* _blossom_rep;
   5.102 -
   5.103 -    IntNodeMap* _tree_set_index;
   5.104 -    TreeSet* _tree_set;
   5.105 -
   5.106 -    NodeQueue _node_queue;
   5.107 -    int _process, _postpone, _last;
   5.108 -
   5.109 -    int _node_num;
   5.110 -
   5.111 -  private:
   5.112 -
   5.113 -    void createStructures() {
   5.114 -      _node_num = countNodes(_graph);
   5.115 -      if (!_matching) {
   5.116 -        _matching = new MatchingMap(_graph);
   5.117 -      }
   5.118 -      if (!_status) {
   5.119 -        _status = new StatusMap(_graph);
   5.120 -      }
   5.121 -      if (!_ear) {
   5.122 -        _ear = new EarMap(_graph);
   5.123 -      }
   5.124 -      if (!_blossom_set) {
   5.125 -        _blossom_set_index = new IntNodeMap(_graph);
   5.126 -        _blossom_set = new BlossomSet(*_blossom_set_index);
   5.127 -      }
   5.128 -      if (!_blossom_rep) {
   5.129 -        _blossom_rep = new NodeIntMap(_node_num);
   5.130 -      }
   5.131 -      if (!_tree_set) {
   5.132 -        _tree_set_index = new IntNodeMap(_graph);
   5.133 -        _tree_set = new TreeSet(*_tree_set_index);
   5.134 -      }
   5.135 -      _node_queue.resize(_node_num);
   5.136 -    }
   5.137 -
   5.138 -    void destroyStructures() {
   5.139 -      if (_matching) {
   5.140 -        delete _matching;
   5.141 -      }
   5.142 -      if (_status) {
   5.143 -        delete _status;
   5.144 -      }
   5.145 -      if (_ear) {
   5.146 -        delete _ear;
   5.147 -      }
   5.148 -      if (_blossom_set) {
   5.149 -        delete _blossom_set;
   5.150 -        delete _blossom_set_index;
   5.151 -      }
   5.152 -      if (_blossom_rep) {
   5.153 -        delete _blossom_rep;
   5.154 -      }
   5.155 -      if (_tree_set) {
   5.156 -        delete _tree_set_index;
   5.157 -        delete _tree_set;
   5.158 -      }
   5.159 -    }
   5.160 -
   5.161 -    void processDense(const Node& n) {
   5.162 -      _process = _postpone = _last = 0;
   5.163 -      _node_queue[_last++] = n;
   5.164 -
   5.165 -      while (_process != _last) {
   5.166 -        Node u = _node_queue[_process++];
   5.167 -        for (OutArcIt a(_graph, u); a != INVALID; ++a) {
   5.168 -          Node v = _graph.target(a);
   5.169 -          if ((*_status)[v] == MATCHED) {
   5.170 -            extendOnArc(a);
   5.171 -          } else if ((*_status)[v] == UNMATCHED) {
   5.172 -            augmentOnArc(a);
   5.173 -            return;
   5.174 -          }
   5.175 -        }
   5.176 -      }
   5.177 -
   5.178 -      while (_postpone != _last) {
   5.179 -        Node u = _node_queue[_postpone++];
   5.180 -
   5.181 -        for (OutArcIt a(_graph, u); a != INVALID ; ++a) {
   5.182 -          Node v = _graph.target(a);
   5.183 -
   5.184 -          if ((*_status)[v] == EVEN) {
   5.185 -            if (_blossom_set->find(u) != _blossom_set->find(v)) {
   5.186 -              shrinkOnEdge(a);
   5.187 -            }
   5.188 -          }
   5.189 -
   5.190 -          while (_process != _last) {
   5.191 -            Node w = _node_queue[_process++];
   5.192 -            for (OutArcIt b(_graph, w); b != INVALID; ++b) {
   5.193 -              Node x = _graph.target(b);
   5.194 -              if ((*_status)[x] == MATCHED) {
   5.195 -                extendOnArc(b);
   5.196 -              } else if ((*_status)[x] == UNMATCHED) {
   5.197 -                augmentOnArc(b);
   5.198 -                return;
   5.199 -              }
   5.200 -            }
   5.201 -          }
   5.202 -        }
   5.203 -      }
   5.204 -    }
   5.205 -
   5.206 -    void processSparse(const Node& n) {
   5.207 -      _process = _last = 0;
   5.208 -      _node_queue[_last++] = n;
   5.209 -      while (_process != _last) {
   5.210 -        Node u = _node_queue[_process++];
   5.211 -        for (OutArcIt a(_graph, u); a != INVALID; ++a) {
   5.212 -          Node v = _graph.target(a);
   5.213 -
   5.214 -          if ((*_status)[v] == EVEN) {
   5.215 -            if (_blossom_set->find(u) != _blossom_set->find(v)) {
   5.216 -              shrinkOnEdge(a);
   5.217 -            }
   5.218 -          } else if ((*_status)[v] == MATCHED) {
   5.219 -            extendOnArc(a);
   5.220 -          } else if ((*_status)[v] == UNMATCHED) {
   5.221 -            augmentOnArc(a);
   5.222 -            return;
   5.223 -          }
   5.224 -        }
   5.225 -      }
   5.226 -    }
   5.227 -
   5.228 -    void shrinkOnEdge(const Edge& e) {
   5.229 -      Node nca = INVALID;
   5.230 -
   5.231 -      {
   5.232 -        std::set<Node> left_set, right_set;
   5.233 -
   5.234 -        Node left = (*_blossom_rep)[_blossom_set->find(_graph.u(e))];
   5.235 -        left_set.insert(left);
   5.236 -
   5.237 -        Node right = (*_blossom_rep)[_blossom_set->find(_graph.v(e))];
   5.238 -        right_set.insert(right);
   5.239 -
   5.240 -        while (true) {
   5.241 -          if ((*_matching)[left] == INVALID) break;
   5.242 -          left = _graph.target((*_matching)[left]);
   5.243 -          left = (*_blossom_rep)[_blossom_set->
   5.244 -                                 find(_graph.target((*_ear)[left]))];
   5.245 -          if (right_set.find(left) != right_set.end()) {
   5.246 -            nca = left;
   5.247 -            break;
   5.248 -          }
   5.249 -          left_set.insert(left);
   5.250 -
   5.251 -          if ((*_matching)[right] == INVALID) break;
   5.252 -          right = _graph.target((*_matching)[right]);
   5.253 -          right = (*_blossom_rep)[_blossom_set->
   5.254 -                                  find(_graph.target((*_ear)[right]))];
   5.255 -          if (left_set.find(right) != left_set.end()) {
   5.256 -            nca = right;
   5.257 -            break;
   5.258 -          }
   5.259 -          right_set.insert(right);
   5.260 -        }
   5.261 -
   5.262 -        if (nca == INVALID) {
   5.263 -          if ((*_matching)[left] == INVALID) {
   5.264 -            nca = right;
   5.265 -            while (left_set.find(nca) == left_set.end()) {
   5.266 -              nca = _graph.target((*_matching)[nca]);
   5.267 -              nca =(*_blossom_rep)[_blossom_set->
   5.268 -                                   find(_graph.target((*_ear)[nca]))];
   5.269 -            }
   5.270 -          } else {
   5.271 -            nca = left;
   5.272 -            while (right_set.find(nca) == right_set.end()) {
   5.273 -              nca = _graph.target((*_matching)[nca]);
   5.274 -              nca = (*_blossom_rep)[_blossom_set->
   5.275 -                                   find(_graph.target((*_ear)[nca]))];
   5.276 -            }
   5.277 -          }
   5.278 -        }
   5.279 -      }
   5.280 -
   5.281 -      {
   5.282 -
   5.283 -        Node node = _graph.u(e);
   5.284 -        Arc arc = _graph.direct(e, true);
   5.285 -        Node base = (*_blossom_rep)[_blossom_set->find(node)];
   5.286 -
   5.287 -        while (base != nca) {
   5.288 -          (*_ear)[node] = arc;
   5.289 -
   5.290 -          Node n = node;
   5.291 -          while (n != base) {
   5.292 -            n = _graph.target((*_matching)[n]);
   5.293 -            Arc a = (*_ear)[n];
   5.294 -            n = _graph.target(a);
   5.295 -            (*_ear)[n] = _graph.oppositeArc(a);
   5.296 -          }
   5.297 -          node = _graph.target((*_matching)[base]);
   5.298 -          _tree_set->erase(base);
   5.299 -          _tree_set->erase(node);
   5.300 -          _blossom_set->insert(node, _blossom_set->find(base));
   5.301 -          (*_status)[node] = EVEN;
   5.302 -          _node_queue[_last++] = node;
   5.303 -          arc = _graph.oppositeArc((*_ear)[node]);
   5.304 -          node = _graph.target((*_ear)[node]);
   5.305 -          base = (*_blossom_rep)[_blossom_set->find(node)];
   5.306 -          _blossom_set->join(_graph.target(arc), base);
   5.307 -        }
   5.308 -      }
   5.309 -
   5.310 -      (*_blossom_rep)[_blossom_set->find(nca)] = nca;
   5.311 -
   5.312 -      {
   5.313 -
   5.314 -        Node node = _graph.v(e);
   5.315 -        Arc arc = _graph.direct(e, false);
   5.316 -        Node base = (*_blossom_rep)[_blossom_set->find(node)];
   5.317 -
   5.318 -        while (base != nca) {
   5.319 -          (*_ear)[node] = arc;
   5.320 -
   5.321 -          Node n = node;
   5.322 -          while (n != base) {
   5.323 -            n = _graph.target((*_matching)[n]);
   5.324 -            Arc a = (*_ear)[n];
   5.325 -            n = _graph.target(a);
   5.326 -            (*_ear)[n] = _graph.oppositeArc(a);
   5.327 -          }
   5.328 -          node = _graph.target((*_matching)[base]);
   5.329 -          _tree_set->erase(base);
   5.330 -          _tree_set->erase(node);
   5.331 -          _blossom_set->insert(node, _blossom_set->find(base));
   5.332 -          (*_status)[node] = EVEN;
   5.333 -          _node_queue[_last++] = node;
   5.334 -          arc = _graph.oppositeArc((*_ear)[node]);
   5.335 -          node = _graph.target((*_ear)[node]);
   5.336 -          base = (*_blossom_rep)[_blossom_set->find(node)];
   5.337 -          _blossom_set->join(_graph.target(arc), base);
   5.338 -        }
   5.339 -      }
   5.340 -
   5.341 -      (*_blossom_rep)[_blossom_set->find(nca)] = nca;
   5.342 -    }
   5.343 -
   5.344 -
   5.345 -
   5.346 -    void extendOnArc(const Arc& a) {
   5.347 -      Node base = _graph.source(a);
   5.348 -      Node odd = _graph.target(a);
   5.349 -
   5.350 -      (*_ear)[odd] = _graph.oppositeArc(a);
   5.351 -      Node even = _graph.target((*_matching)[odd]);
   5.352 -      (*_blossom_rep)[_blossom_set->insert(even)] = even;
   5.353 -      (*_status)[odd] = ODD;
   5.354 -      (*_status)[even] = EVEN;
   5.355 -      int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(base)]);
   5.356 -      _tree_set->insert(odd, tree);
   5.357 -      _tree_set->insert(even, tree);
   5.358 -      _node_queue[_last++] = even;
   5.359 -
   5.360 -    }
   5.361 -
   5.362 -    void augmentOnArc(const Arc& a) {
   5.363 -      Node even = _graph.source(a);
   5.364 -      Node odd = _graph.target(a);
   5.365 -
   5.366 -      int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(even)]);
   5.367 -
   5.368 -      (*_matching)[odd] = _graph.oppositeArc(a);
   5.369 -      (*_status)[odd] = MATCHED;
   5.370 -
   5.371 -      Arc arc = (*_matching)[even];
   5.372 -      (*_matching)[even] = a;
   5.373 -
   5.374 -      while (arc != INVALID) {
   5.375 -        odd = _graph.target(arc);
   5.376 -        arc = (*_ear)[odd];
   5.377 -        even = _graph.target(arc);
   5.378 -        (*_matching)[odd] = arc;
   5.379 -        arc = (*_matching)[even];
   5.380 -        (*_matching)[even] = _graph.oppositeArc((*_matching)[odd]);
   5.381 -      }
   5.382 -
   5.383 -      for (typename TreeSet::ItemIt it(*_tree_set, tree);
   5.384 -           it != INVALID; ++it) {
   5.385 -        if ((*_status)[it] == ODD) {
   5.386 -          (*_status)[it] = MATCHED;
   5.387 -        } else {
   5.388 -          int blossom = _blossom_set->find(it);
   5.389 -          for (typename BlossomSet::ItemIt jt(*_blossom_set, blossom);
   5.390 -               jt != INVALID; ++jt) {
   5.391 -            (*_status)[jt] = MATCHED;
   5.392 -          }
   5.393 -          _blossom_set->eraseClass(blossom);
   5.394 -        }
   5.395 -      }
   5.396 -      _tree_set->eraseClass(tree);
   5.397 -
   5.398 -    }
   5.399 -
   5.400 -  public:
   5.401 -
   5.402 -    /// \brief Constructor
   5.403 -    ///
   5.404 -    /// Constructor.
   5.405 -    MaxMatching(const Graph& graph)
   5.406 -      : _graph(graph), _matching(0), _status(0), _ear(0),
   5.407 -        _blossom_set_index(0), _blossom_set(0), _blossom_rep(0),
   5.408 -        _tree_set_index(0), _tree_set(0) {}
   5.409 -
   5.410 -    ~MaxMatching() {
   5.411 -      destroyStructures();
   5.412 -    }
   5.413 -
   5.414 -    /// \name Execution control
   5.415 -    /// The simplest way to execute the algorithm is to use the
   5.416 -    /// \c run() member function.
   5.417 -    /// \n
   5.418 -
   5.419 -    /// If you need better control on the execution, you must call
   5.420 -    /// \ref init(), \ref greedyInit() or \ref matchingInit()
   5.421 -    /// functions first, then you can start the algorithm with the \ref
   5.422 -    /// startSparse() or startDense() functions.
   5.423 -
   5.424 -    ///@{
   5.425 -
   5.426 -    /// \brief Sets the actual matching to the empty matching.
   5.427 -    ///
   5.428 -    /// Sets the actual matching to the empty matching.
   5.429 -    ///
   5.430 -    void init() {
   5.431 -      createStructures();
   5.432 -      for(NodeIt n(_graph); n != INVALID; ++n) {
   5.433 -        (*_matching)[n] = INVALID;
   5.434 -        (*_status)[n] = UNMATCHED;
   5.435 -      }
   5.436 -    }
   5.437 -
   5.438 -    ///\brief Finds an initial matching in a greedy way
   5.439 -    ///
   5.440 -    ///It finds an initial matching in a greedy way.
   5.441 -    void greedyInit() {
   5.442 -      createStructures();
   5.443 -      for (NodeIt n(_graph); n != INVALID; ++n) {
   5.444 -        (*_matching)[n] = INVALID;
   5.445 -        (*_status)[n] = UNMATCHED;
   5.446 -      }
   5.447 -      for (NodeIt n(_graph); n != INVALID; ++n) {
   5.448 -        if ((*_matching)[n] == INVALID) {
   5.449 -          for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
   5.450 -            Node v = _graph.target(a);
   5.451 -            if ((*_matching)[v] == INVALID && v != n) {
   5.452 -              (*_matching)[n] = a;
   5.453 -              (*_status)[n] = MATCHED;
   5.454 -              (*_matching)[v] = _graph.oppositeArc(a);
   5.455 -              (*_status)[v] = MATCHED;
   5.456 -              break;
   5.457 -            }
   5.458 -          }
   5.459 -        }
   5.460 -      }
   5.461 -    }
   5.462 -
   5.463 -
   5.464 -    /// \brief Initialize the matching from a map containing.
   5.465 -    ///
   5.466 -    /// Initialize the matching from a \c bool valued \c Edge map. This
   5.467 -    /// map must have the property that there are no two incident edges
   5.468 -    /// with true value, ie. it contains a matching.
   5.469 -    /// \return \c true if the map contains a matching.
   5.470 -    template <typename MatchingMap>
   5.471 -    bool matchingInit(const MatchingMap& matching) {
   5.472 -      createStructures();
   5.473 -
   5.474 -      for (NodeIt n(_graph); n != INVALID; ++n) {
   5.475 -        (*_matching)[n] = INVALID;
   5.476 -        (*_status)[n] = UNMATCHED;
   5.477 -      }
   5.478 -      for(EdgeIt e(_graph); e!=INVALID; ++e) {
   5.479 -        if (matching[e]) {
   5.480 -
   5.481 -          Node u = _graph.u(e);
   5.482 -          if ((*_matching)[u] != INVALID) return false;
   5.483 -          (*_matching)[u] = _graph.direct(e, true);
   5.484 -          (*_status)[u] = MATCHED;
   5.485 -
   5.486 -          Node v = _graph.v(e);
   5.487 -          if ((*_matching)[v] != INVALID) return false;
   5.488 -          (*_matching)[v] = _graph.direct(e, false);
   5.489 -          (*_status)[v] = MATCHED;
   5.490 -        }
   5.491 -      }
   5.492 -      return true;
   5.493 -    }
   5.494 -
   5.495 -    /// \brief Starts Edmonds' algorithm
   5.496 -    ///
   5.497 -    /// If runs the original Edmonds' algorithm.
   5.498 -    void startSparse() {
   5.499 -      for(NodeIt n(_graph); n != INVALID; ++n) {
   5.500 -        if ((*_status)[n] == UNMATCHED) {
   5.501 -          (*_blossom_rep)[_blossom_set->insert(n)] = n;
   5.502 -          _tree_set->insert(n);
   5.503 -          (*_status)[n] = EVEN;
   5.504 -          processSparse(n);
   5.505 -        }
   5.506 -      }
   5.507 -    }
   5.508 -
   5.509 -    /// \brief Starts Edmonds' algorithm.
   5.510 -    ///
   5.511 -    /// It runs Edmonds' algorithm with a heuristic of postponing
   5.512 -    /// shrinks, therefore resulting in a faster algorithm for dense graphs.
   5.513 -    void startDense() {
   5.514 -      for(NodeIt n(_graph); n != INVALID; ++n) {
   5.515 -        if ((*_status)[n] == UNMATCHED) {
   5.516 -          (*_blossom_rep)[_blossom_set->insert(n)] = n;
   5.517 -          _tree_set->insert(n);
   5.518 -          (*_status)[n] = EVEN;
   5.519 -          processDense(n);
   5.520 -        }
   5.521 -      }
   5.522 -    }
   5.523 -
   5.524 -
   5.525 -    /// \brief Runs Edmonds' algorithm
   5.526 -    ///
   5.527 -    /// Runs Edmonds' algorithm for sparse graphs (<tt>m<2*n</tt>)
   5.528 -    /// or Edmonds' algorithm with a heuristic of
   5.529 -    /// postponing shrinks for dense graphs.
   5.530 -    void run() {
   5.531 -      if (countEdges(_graph) < 2 * countNodes(_graph)) {
   5.532 -        greedyInit();
   5.533 -        startSparse();
   5.534 -      } else {
   5.535 -        init();
   5.536 -        startDense();
   5.537 -      }
   5.538 -    }
   5.539 -
   5.540 -    /// @}
   5.541 -
   5.542 -    /// \name Primal solution
   5.543 -    /// Functions to get the primal solution, ie. the matching.
   5.544 -
   5.545 -    /// @{
   5.546 -
   5.547 -    ///\brief Returns the size of the current matching.
   5.548 -    ///
   5.549 -    ///Returns the size of the current matching. After \ref
   5.550 -    ///run() it returns the size of the maximum matching in the graph.
   5.551 -    int matchingSize() const {
   5.552 -      int size = 0;
   5.553 -      for (NodeIt n(_graph); n != INVALID; ++n) {
   5.554 -        if ((*_matching)[n] != INVALID) {
   5.555 -          ++size;
   5.556 -        }
   5.557 -      }
   5.558 -      return size / 2;
   5.559 -    }
   5.560 -
   5.561 -    /// \brief Returns true when the edge is in the matching.
   5.562 -    ///
   5.563 -    /// Returns true when the edge is in the matching.
   5.564 -    bool matching(const Edge& edge) const {
   5.565 -      return edge == (*_matching)[_graph.u(edge)];
   5.566 -    }
   5.567 -
   5.568 -    /// \brief Returns the matching edge incident to the given node.
   5.569 -    ///
   5.570 -    /// Returns the matching edge of a \c node in the actual matching or
   5.571 -    /// INVALID if the \c node is not covered by the actual matching.
   5.572 -    Arc matching(const Node& n) const {
   5.573 -      return (*_matching)[n];
   5.574 -    }
   5.575 -
   5.576 -    ///\brief Returns the mate of a node in the actual matching.
   5.577 -    ///
   5.578 -    ///Returns the mate of a \c node in the actual matching or
   5.579 -    ///INVALID if the \c node is not covered by the actual matching.
   5.580 -    Node mate(const Node& n) const {
   5.581 -      return (*_matching)[n] != INVALID ?
   5.582 -        _graph.target((*_matching)[n]) : INVALID;
   5.583 -    }
   5.584 -
   5.585 -    /// @}
   5.586 -
   5.587 -    /// \name Dual solution
   5.588 -    /// Functions to get the dual solution, ie. the decomposition.
   5.589 -
   5.590 -    /// @{
   5.591 -
   5.592 -    /// \brief Returns the class of the node in the Edmonds-Gallai
   5.593 -    /// decomposition.
   5.594 -    ///
   5.595 -    /// Returns the class of the node in the Edmonds-Gallai
   5.596 -    /// decomposition.
   5.597 -    Status decomposition(const Node& n) const {
   5.598 -      return (*_status)[n];
   5.599 -    }
   5.600 -
   5.601 -    /// \brief Returns true when the node is in the barrier.
   5.602 -    ///
   5.603 -    /// Returns true when the node is in the barrier.
   5.604 -    bool barrier(const Node& n) const {
   5.605 -      return (*_status)[n] == ODD;
   5.606 -    }
   5.607 -
   5.608 -    /// @}
   5.609 -
   5.610 -  };
   5.611 -
   5.612 -  /// \ingroup matching
   5.613 -  ///
   5.614 -  /// \brief Weighted matching in general graphs
   5.615 -  ///
   5.616 -  /// This class provides an efficient implementation of Edmond's
   5.617 -  /// maximum weighted matching algorithm. The implementation is based
   5.618 -  /// on extensive use of priority queues and provides
   5.619 -  /// \f$O(nm\log n)\f$ time complexity.
   5.620 -  ///
   5.621 -  /// The maximum weighted matching problem is to find undirected
   5.622 -  /// edges in the graph with maximum overall weight and no two of
   5.623 -  /// them shares their ends. The problem can be formulated with the
   5.624 -  /// following linear program.
   5.625 -  /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
   5.626 -  /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
   5.627 -      \quad \forall B\in\mathcal{O}\f] */
   5.628 -  /// \f[x_e \ge 0\quad \forall e\in E\f]
   5.629 -  /// \f[\max \sum_{e\in E}x_ew_e\f]
   5.630 -  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
   5.631 -  /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
   5.632 -  /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
   5.633 -  /// subsets of the nodes.
   5.634 -  ///
   5.635 -  /// The algorithm calculates an optimal matching and a proof of the
   5.636 -  /// optimality. The solution of the dual problem can be used to check
   5.637 -  /// the result of the algorithm. The dual linear problem is the
   5.638 -  /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}
   5.639 -      z_B \ge w_{uv} \quad \forall uv\in E\f] */
   5.640 -  /// \f[y_u \ge 0 \quad \forall u \in V\f]
   5.641 -  /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
   5.642 -  /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
   5.643 -      \frac{\vert B \vert - 1}{2}z_B\f] */
   5.644 -  ///
   5.645 -  /// The algorithm can be executed with \c run() or the \c init() and
   5.646 -  /// then the \c start() member functions. After it the matching can
   5.647 -  /// be asked with \c matching() or mate() functions. The dual
   5.648 -  /// solution can be get with \c nodeValue(), \c blossomNum() and \c
   5.649 -  /// blossomValue() members and \ref MaxWeightedMatching::BlossomIt
   5.650 -  /// "BlossomIt" nested class, which is able to iterate on the nodes
   5.651 -  /// of a blossom. If the value type is integral then the dual
   5.652 -  /// solution is multiplied by \ref MaxWeightedMatching::dualScale "4".
   5.653 -  template <typename GR,
   5.654 -            typename WM = typename GR::template EdgeMap<int> >
   5.655 -  class MaxWeightedMatching {
   5.656 -  public:
   5.657 -
   5.658 -    ///\e
   5.659 -    typedef GR Graph;
   5.660 -    ///\e
   5.661 -    typedef WM WeightMap;
   5.662 -    ///\e
   5.663 -    typedef typename WeightMap::Value Value;
   5.664 -
   5.665 -    /// \brief Scaling factor for dual solution
   5.666 -    ///
   5.667 -    /// Scaling factor for dual solution, it is equal to 4 or 1
   5.668 -    /// according to the value type.
   5.669 -    static const int dualScale =
   5.670 -      std::numeric_limits<Value>::is_integer ? 4 : 1;
   5.671 -
   5.672 -    typedef typename Graph::template NodeMap<typename Graph::Arc>
   5.673 -    MatchingMap;
   5.674 -
   5.675 -  private:
   5.676 -
   5.677 -    TEMPLATE_GRAPH_TYPEDEFS(Graph);
   5.678 -
   5.679 -    typedef typename Graph::template NodeMap<Value> NodePotential;
   5.680 -    typedef std::vector<Node> BlossomNodeList;
   5.681 -
   5.682 -    struct BlossomVariable {
   5.683 -      int begin, end;
   5.684 -      Value value;
   5.685 -
   5.686 -      BlossomVariable(int _begin, int _end, Value _value)
   5.687 -        : begin(_begin), end(_end), value(_value) {}
   5.688 -
   5.689 -    };
   5.690 -
   5.691 -    typedef std::vector<BlossomVariable> BlossomPotential;
   5.692 -
   5.693 -    const Graph& _graph;
   5.694 -    const WeightMap& _weight;
   5.695 -
   5.696 -    MatchingMap* _matching;
   5.697 -
   5.698 -    NodePotential* _node_potential;
   5.699 -
   5.700 -    BlossomPotential _blossom_potential;
   5.701 -    BlossomNodeList _blossom_node_list;
   5.702 -
   5.703 -    int _node_num;
   5.704 -    int _blossom_num;
   5.705 -
   5.706 -    typedef RangeMap<int> IntIntMap;
   5.707 -
   5.708 -    enum Status {
   5.709 -      EVEN = -1, MATCHED = 0, ODD = 1, UNMATCHED = -2
   5.710 -    };
   5.711 -
   5.712 -    typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
   5.713 -    struct BlossomData {
   5.714 -      int tree;
   5.715 -      Status status;
   5.716 -      Arc pred, next;
   5.717 -      Value pot, offset;
   5.718 -      Node base;
   5.719 -    };
   5.720 -
   5.721 -    IntNodeMap *_blossom_index;
   5.722 -    BlossomSet *_blossom_set;
   5.723 -    RangeMap<BlossomData>* _blossom_data;
   5.724 -
   5.725 -    IntNodeMap *_node_index;
   5.726 -    IntArcMap *_node_heap_index;
   5.727 -
   5.728 -    struct NodeData {
   5.729 -
   5.730 -      NodeData(IntArcMap& node_heap_index)
   5.731 -        : heap(node_heap_index) {}
   5.732 -
   5.733 -      int blossom;
   5.734 -      Value pot;
   5.735 -      BinHeap<Value, IntArcMap> heap;
   5.736 -      std::map<int, Arc> heap_index;
   5.737 -
   5.738 -      int tree;
   5.739 -    };
   5.740 -
   5.741 -    RangeMap<NodeData>* _node_data;
   5.742 -
   5.743 -    typedef ExtendFindEnum<IntIntMap> TreeSet;
   5.744 -
   5.745 -    IntIntMap *_tree_set_index;
   5.746 -    TreeSet *_tree_set;
   5.747 -
   5.748 -    IntNodeMap *_delta1_index;
   5.749 -    BinHeap<Value, IntNodeMap> *_delta1;
   5.750 -
   5.751 -    IntIntMap *_delta2_index;
   5.752 -    BinHeap<Value, IntIntMap> *_delta2;
   5.753 -
   5.754 -    IntEdgeMap *_delta3_index;
   5.755 -    BinHeap<Value, IntEdgeMap> *_delta3;
   5.756 -
   5.757 -    IntIntMap *_delta4_index;
   5.758 -    BinHeap<Value, IntIntMap> *_delta4;
   5.759 -
   5.760 -    Value _delta_sum;
   5.761 -
   5.762 -    void createStructures() {
   5.763 -      _node_num = countNodes(_graph);
   5.764 -      _blossom_num = _node_num * 3 / 2;
   5.765 -
   5.766 -      if (!_matching) {
   5.767 -        _matching = new MatchingMap(_graph);
   5.768 -      }
   5.769 -      if (!_node_potential) {
   5.770 -        _node_potential = new NodePotential(_graph);
   5.771 -      }
   5.772 -      if (!_blossom_set) {
   5.773 -        _blossom_index = new IntNodeMap(_graph);
   5.774 -        _blossom_set = new BlossomSet(*_blossom_index);
   5.775 -        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
   5.776 -      }
   5.777 -
   5.778 -      if (!_node_index) {
   5.779 -        _node_index = new IntNodeMap(_graph);
   5.780 -        _node_heap_index = new IntArcMap(_graph);
   5.781 -        _node_data = new RangeMap<NodeData>(_node_num,
   5.782 -                                              NodeData(*_node_heap_index));
   5.783 -      }
   5.784 -
   5.785 -      if (!_tree_set) {
   5.786 -        _tree_set_index = new IntIntMap(_blossom_num);
   5.787 -        _tree_set = new TreeSet(*_tree_set_index);
   5.788 -      }
   5.789 -      if (!_delta1) {
   5.790 -        _delta1_index = new IntNodeMap(_graph);
   5.791 -        _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
   5.792 -      }
   5.793 -      if (!_delta2) {
   5.794 -        _delta2_index = new IntIntMap(_blossom_num);
   5.795 -        _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
   5.796 -      }
   5.797 -      if (!_delta3) {
   5.798 -        _delta3_index = new IntEdgeMap(_graph);
   5.799 -        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
   5.800 -      }
   5.801 -      if (!_delta4) {
   5.802 -        _delta4_index = new IntIntMap(_blossom_num);
   5.803 -        _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
   5.804 -      }
   5.805 -    }
   5.806 -
   5.807 -    void destroyStructures() {
   5.808 -      _node_num = countNodes(_graph);
   5.809 -      _blossom_num = _node_num * 3 / 2;
   5.810 -
   5.811 -      if (_matching) {
   5.812 -        delete _matching;
   5.813 -      }
   5.814 -      if (_node_potential) {
   5.815 -        delete _node_potential;
   5.816 -      }
   5.817 -      if (_blossom_set) {
   5.818 -        delete _blossom_index;
   5.819 -        delete _blossom_set;
   5.820 -        delete _blossom_data;
   5.821 -      }
   5.822 -
   5.823 -      if (_node_index) {
   5.824 -        delete _node_index;
   5.825 -        delete _node_heap_index;
   5.826 -        delete _node_data;
   5.827 -      }
   5.828 -
   5.829 -      if (_tree_set) {
   5.830 -        delete _tree_set_index;
   5.831 -        delete _tree_set;
   5.832 -      }
   5.833 -      if (_delta1) {
   5.834 -        delete _delta1_index;
   5.835 -        delete _delta1;
   5.836 -      }
   5.837 -      if (_delta2) {
   5.838 -        delete _delta2_index;
   5.839 -        delete _delta2;
   5.840 -      }
   5.841 -      if (_delta3) {
   5.842 -        delete _delta3_index;
   5.843 -        delete _delta3;
   5.844 -      }
   5.845 -      if (_delta4) {
   5.846 -        delete _delta4_index;
   5.847 -        delete _delta4;
   5.848 -      }
   5.849 -    }
   5.850 -
   5.851 -    void matchedToEven(int blossom, int tree) {
   5.852 -      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
   5.853 -        _delta2->erase(blossom);
   5.854 -      }
   5.855 -
   5.856 -      if (!_blossom_set->trivial(blossom)) {
   5.857 -        (*_blossom_data)[blossom].pot -=
   5.858 -          2 * (_delta_sum - (*_blossom_data)[blossom].offset);
   5.859 -      }
   5.860 -
   5.861 -      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
   5.862 -           n != INVALID; ++n) {
   5.863 -
   5.864 -        _blossom_set->increase(n, std::numeric_limits<Value>::max());
   5.865 -        int ni = (*_node_index)[n];
   5.866 -
   5.867 -        (*_node_data)[ni].heap.clear();
   5.868 -        (*_node_data)[ni].heap_index.clear();
   5.869 -
   5.870 -        (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
   5.871 -
   5.872 -        _delta1->push(n, (*_node_data)[ni].pot);
   5.873 -
   5.874 -        for (InArcIt e(_graph, n); e != INVALID; ++e) {
   5.875 -          Node v = _graph.source(e);
   5.876 -          int vb = _blossom_set->find(v);
   5.877 -          int vi = (*_node_index)[v];
   5.878 -
   5.879 -          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
   5.880 -            dualScale * _weight[e];
   5.881 -
   5.882 -          if ((*_blossom_data)[vb].status == EVEN) {
   5.883 -            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
   5.884 -              _delta3->push(e, rw / 2);
   5.885 -            }
   5.886 -          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
   5.887 -            if (_delta3->state(e) != _delta3->IN_HEAP) {
   5.888 -              _delta3->push(e, rw);
   5.889 -            }
   5.890 -          } else {
   5.891 -            typename std::map<int, Arc>::iterator it =
   5.892 -              (*_node_data)[vi].heap_index.find(tree);
   5.893 -
   5.894 -            if (it != (*_node_data)[vi].heap_index.end()) {
   5.895 -              if ((*_node_data)[vi].heap[it->second] > rw) {
   5.896 -                (*_node_data)[vi].heap.replace(it->second, e);
   5.897 -                (*_node_data)[vi].heap.decrease(e, rw);
   5.898 -                it->second = e;
   5.899 -              }
   5.900 -            } else {
   5.901 -              (*_node_data)[vi].heap.push(e, rw);
   5.902 -              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
   5.903 -            }
   5.904 -
   5.905 -            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
   5.906 -              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
   5.907 -
   5.908 -              if ((*_blossom_data)[vb].status == MATCHED) {
   5.909 -                if (_delta2->state(vb) != _delta2->IN_HEAP) {
   5.910 -                  _delta2->push(vb, _blossom_set->classPrio(vb) -
   5.911 -                               (*_blossom_data)[vb].offset);
   5.912 -                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
   5.913 -                           (*_blossom_data)[vb].offset){
   5.914 -                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
   5.915 -                                   (*_blossom_data)[vb].offset);
   5.916 -                }
   5.917 -              }
   5.918 -            }
   5.919 -          }
   5.920 -        }
   5.921 -      }
   5.922 -      (*_blossom_data)[blossom].offset = 0;
   5.923 -    }
   5.924 -
   5.925 -    void matchedToOdd(int blossom) {
   5.926 -      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
   5.927 -        _delta2->erase(blossom);
   5.928 -      }
   5.929 -      (*_blossom_data)[blossom].offset += _delta_sum;
   5.930 -      if (!_blossom_set->trivial(blossom)) {
   5.931 -        _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
   5.932 -                     (*_blossom_data)[blossom].offset);
   5.933 -      }
   5.934 -    }
   5.935 -
   5.936 -    void evenToMatched(int blossom, int tree) {
   5.937 -      if (!_blossom_set->trivial(blossom)) {
   5.938 -        (*_blossom_data)[blossom].pot += 2 * _delta_sum;
   5.939 -      }
   5.940 -
   5.941 -      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
   5.942 -           n != INVALID; ++n) {
   5.943 -        int ni = (*_node_index)[n];
   5.944 -        (*_node_data)[ni].pot -= _delta_sum;
   5.945 -
   5.946 -        _delta1->erase(n);
   5.947 -
   5.948 -        for (InArcIt e(_graph, n); e != INVALID; ++e) {
   5.949 -          Node v = _graph.source(e);
   5.950 -          int vb = _blossom_set->find(v);
   5.951 -          int vi = (*_node_index)[v];
   5.952 -
   5.953 -          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
   5.954 -            dualScale * _weight[e];
   5.955 -
   5.956 -          if (vb == blossom) {
   5.957 -            if (_delta3->state(e) == _delta3->IN_HEAP) {
   5.958 -              _delta3->erase(e);
   5.959 -            }
   5.960 -          } else if ((*_blossom_data)[vb].status == EVEN) {
   5.961 -
   5.962 -            if (_delta3->state(e) == _delta3->IN_HEAP) {
   5.963 -              _delta3->erase(e);
   5.964 -            }
   5.965 -
   5.966 -            int vt = _tree_set->find(vb);
   5.967 -
   5.968 -            if (vt != tree) {
   5.969 -
   5.970 -              Arc r = _graph.oppositeArc(e);
   5.971 -
   5.972 -              typename std::map<int, Arc>::iterator it =
   5.973 -                (*_node_data)[ni].heap_index.find(vt);
   5.974 -
   5.975 -              if (it != (*_node_data)[ni].heap_index.end()) {
   5.976 -                if ((*_node_data)[ni].heap[it->second] > rw) {
   5.977 -                  (*_node_data)[ni].heap.replace(it->second, r);
   5.978 -                  (*_node_data)[ni].heap.decrease(r, rw);
   5.979 -                  it->second = r;
   5.980 -                }
   5.981 -              } else {
   5.982 -                (*_node_data)[ni].heap.push(r, rw);
   5.983 -                (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
   5.984 -              }
   5.985 -
   5.986 -              if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
   5.987 -                _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
   5.988 -
   5.989 -                if (_delta2->state(blossom) != _delta2->IN_HEAP) {
   5.990 -                  _delta2->push(blossom, _blossom_set->classPrio(blossom) -
   5.991 -                               (*_blossom_data)[blossom].offset);
   5.992 -                } else if ((*_delta2)[blossom] >
   5.993 -                           _blossom_set->classPrio(blossom) -
   5.994 -                           (*_blossom_data)[blossom].offset){
   5.995 -                  _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
   5.996 -                                   (*_blossom_data)[blossom].offset);
   5.997 -                }
   5.998 -              }
   5.999 -            }
  5.1000 -
  5.1001 -          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
  5.1002 -            if (_delta3->state(e) == _delta3->IN_HEAP) {
  5.1003 -              _delta3->erase(e);
  5.1004 -            }
  5.1005 -          } else {
  5.1006 -
  5.1007 -            typename std::map<int, Arc>::iterator it =
  5.1008 -              (*_node_data)[vi].heap_index.find(tree);
  5.1009 -
  5.1010 -            if (it != (*_node_data)[vi].heap_index.end()) {
  5.1011 -              (*_node_data)[vi].heap.erase(it->second);
  5.1012 -              (*_node_data)[vi].heap_index.erase(it);
  5.1013 -              if ((*_node_data)[vi].heap.empty()) {
  5.1014 -                _blossom_set->increase(v, std::numeric_limits<Value>::max());
  5.1015 -              } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
  5.1016 -                _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
  5.1017 -              }
  5.1018 -
  5.1019 -              if ((*_blossom_data)[vb].status == MATCHED) {
  5.1020 -                if (_blossom_set->classPrio(vb) ==
  5.1021 -                    std::numeric_limits<Value>::max()) {
  5.1022 -                  _delta2->erase(vb);
  5.1023 -                } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
  5.1024 -                           (*_blossom_data)[vb].offset) {
  5.1025 -                  _delta2->increase(vb, _blossom_set->classPrio(vb) -
  5.1026 -                                   (*_blossom_data)[vb].offset);
  5.1027 -                }
  5.1028 -              }
  5.1029 -            }
  5.1030 -          }
  5.1031 -        }
  5.1032 -      }
  5.1033 -    }
  5.1034 -
  5.1035 -    void oddToMatched(int blossom) {
  5.1036 -      (*_blossom_data)[blossom].offset -= _delta_sum;
  5.1037 -
  5.1038 -      if (_blossom_set->classPrio(blossom) !=
  5.1039 -          std::numeric_limits<Value>::max()) {
  5.1040 -        _delta2->push(blossom, _blossom_set->classPrio(blossom) -
  5.1041 -                       (*_blossom_data)[blossom].offset);
  5.1042 -      }
  5.1043 -
  5.1044 -      if (!_blossom_set->trivial(blossom)) {
  5.1045 -        _delta4->erase(blossom);
  5.1046 -      }
  5.1047 -    }
  5.1048 -
  5.1049 -    void oddToEven(int blossom, int tree) {
  5.1050 -      if (!_blossom_set->trivial(blossom)) {
  5.1051 -        _delta4->erase(blossom);
  5.1052 -        (*_blossom_data)[blossom].pot -=
  5.1053 -          2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
  5.1054 -      }
  5.1055 -
  5.1056 -      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  5.1057 -           n != INVALID; ++n) {
  5.1058 -        int ni = (*_node_index)[n];
  5.1059 -
  5.1060 -        _blossom_set->increase(n, std::numeric_limits<Value>::max());
  5.1061 -
  5.1062 -        (*_node_data)[ni].heap.clear();
  5.1063 -        (*_node_data)[ni].heap_index.clear();
  5.1064 -        (*_node_data)[ni].pot +=
  5.1065 -          2 * _delta_sum - (*_blossom_data)[blossom].offset;
  5.1066 -
  5.1067 -        _delta1->push(n, (*_node_data)[ni].pot);
  5.1068 -
  5.1069 -        for (InArcIt e(_graph, n); e != INVALID; ++e) {
  5.1070 -          Node v = _graph.source(e);
  5.1071 -          int vb = _blossom_set->find(v);
  5.1072 -          int vi = (*_node_index)[v];
  5.1073 -
  5.1074 -          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  5.1075 -            dualScale * _weight[e];
  5.1076 -
  5.1077 -          if ((*_blossom_data)[vb].status == EVEN) {
  5.1078 -            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
  5.1079 -              _delta3->push(e, rw / 2);
  5.1080 -            }
  5.1081 -          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
  5.1082 -            if (_delta3->state(e) != _delta3->IN_HEAP) {
  5.1083 -              _delta3->push(e, rw);
  5.1084 -            }
  5.1085 -          } else {
  5.1086 -
  5.1087 -            typename std::map<int, Arc>::iterator it =
  5.1088 -              (*_node_data)[vi].heap_index.find(tree);
  5.1089 -
  5.1090 -            if (it != (*_node_data)[vi].heap_index.end()) {
  5.1091 -              if ((*_node_data)[vi].heap[it->second] > rw) {
  5.1092 -                (*_node_data)[vi].heap.replace(it->second, e);
  5.1093 -                (*_node_data)[vi].heap.decrease(e, rw);
  5.1094 -                it->second = e;
  5.1095 -              }
  5.1096 -            } else {
  5.1097 -              (*_node_data)[vi].heap.push(e, rw);
  5.1098 -              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
  5.1099 -            }
  5.1100 -
  5.1101 -            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
  5.1102 -              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
  5.1103 -
  5.1104 -              if ((*_blossom_data)[vb].status == MATCHED) {
  5.1105 -                if (_delta2->state(vb) != _delta2->IN_HEAP) {
  5.1106 -                  _delta2->push(vb, _blossom_set->classPrio(vb) -
  5.1107 -                               (*_blossom_data)[vb].offset);
  5.1108 -                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
  5.1109 -                           (*_blossom_data)[vb].offset) {
  5.1110 -                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
  5.1111 -                                   (*_blossom_data)[vb].offset);
  5.1112 -                }
  5.1113 -              }
  5.1114 -            }
  5.1115 -          }
  5.1116 -        }
  5.1117 -      }
  5.1118 -      (*_blossom_data)[blossom].offset = 0;
  5.1119 -    }
  5.1120 -
  5.1121 -
  5.1122 -    void matchedToUnmatched(int blossom) {
  5.1123 -      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
  5.1124 -        _delta2->erase(blossom);
  5.1125 -      }
  5.1126 -
  5.1127 -      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  5.1128 -           n != INVALID; ++n) {
  5.1129 -        int ni = (*_node_index)[n];
  5.1130 -
  5.1131 -        _blossom_set->increase(n, std::numeric_limits<Value>::max());
  5.1132 -
  5.1133 -        (*_node_data)[ni].heap.clear();
  5.1134 -        (*_node_data)[ni].heap_index.clear();
  5.1135 -
  5.1136 -        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
  5.1137 -          Node v = _graph.target(e);
  5.1138 -          int vb = _blossom_set->find(v);
  5.1139 -          int vi = (*_node_index)[v];
  5.1140 -
  5.1141 -          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  5.1142 -            dualScale * _weight[e];
  5.1143 -
  5.1144 -          if ((*_blossom_data)[vb].status == EVEN) {
  5.1145 -            if (_delta3->state(e) != _delta3->IN_HEAP) {
  5.1146 -              _delta3->push(e, rw);
  5.1147 -            }
  5.1148 -          }
  5.1149 -        }
  5.1150 -      }
  5.1151 -    }
  5.1152 -
  5.1153 -    void unmatchedToMatched(int blossom) {
  5.1154 -      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  5.1155 -           n != INVALID; ++n) {
  5.1156 -        int ni = (*_node_index)[n];
  5.1157 -
  5.1158 -        for (InArcIt e(_graph, n); e != INVALID; ++e) {
  5.1159 -          Node v = _graph.source(e);
  5.1160 -          int vb = _blossom_set->find(v);
  5.1161 -          int vi = (*_node_index)[v];
  5.1162 -
  5.1163 -          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  5.1164 -            dualScale * _weight[e];
  5.1165 -
  5.1166 -          if (vb == blossom) {
  5.1167 -            if (_delta3->state(e) == _delta3->IN_HEAP) {
  5.1168 -              _delta3->erase(e);
  5.1169 -            }
  5.1170 -          } else if ((*_blossom_data)[vb].status == EVEN) {
  5.1171 -
  5.1172 -            if (_delta3->state(e) == _delta3->IN_HEAP) {
  5.1173 -              _delta3->erase(e);
  5.1174 -            }
  5.1175 -
  5.1176 -            int vt = _tree_set->find(vb);
  5.1177 -
  5.1178 -            Arc r = _graph.oppositeArc(e);
  5.1179 -
  5.1180 -            typename std::map<int, Arc>::iterator it =
  5.1181 -              (*_node_data)[ni].heap_index.find(vt);
  5.1182 -
  5.1183 -            if (it != (*_node_data)[ni].heap_index.end()) {
  5.1184 -              if ((*_node_data)[ni].heap[it->second] > rw) {
  5.1185 -                (*_node_data)[ni].heap.replace(it->second, r);
  5.1186 -                (*_node_data)[ni].heap.decrease(r, rw);
  5.1187 -                it->second = r;
  5.1188 -              }
  5.1189 -            } else {
  5.1190 -              (*_node_data)[ni].heap.push(r, rw);
  5.1191 -              (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
  5.1192 -            }
  5.1193 -
  5.1194 -            if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
  5.1195 -              _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
  5.1196 -
  5.1197 -              if (_delta2->state(blossom) != _delta2->IN_HEAP) {
  5.1198 -                _delta2->push(blossom, _blossom_set->classPrio(blossom) -
  5.1199 -                             (*_blossom_data)[blossom].offset);
  5.1200 -              } else if ((*_delta2)[blossom] > _blossom_set->classPrio(blossom)-
  5.1201 -                         (*_blossom_data)[blossom].offset){
  5.1202 -                _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
  5.1203 -                                 (*_blossom_data)[blossom].offset);
  5.1204 -              }
  5.1205 -            }
  5.1206 -
  5.1207 -          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
  5.1208 -            if (_delta3->state(e) == _delta3->IN_HEAP) {
  5.1209 -              _delta3->erase(e);
  5.1210 -            }
  5.1211 -          }
  5.1212 -        }
  5.1213 -      }
  5.1214 -    }
  5.1215 -
  5.1216 -    void alternatePath(int even, int tree) {
  5.1217 -      int odd;
  5.1218 -
  5.1219 -      evenToMatched(even, tree);
  5.1220 -      (*_blossom_data)[even].status = MATCHED;
  5.1221 -
  5.1222 -      while ((*_blossom_data)[even].pred != INVALID) {
  5.1223 -        odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
  5.1224 -        (*_blossom_data)[odd].status = MATCHED;
  5.1225 -        oddToMatched(odd);
  5.1226 -        (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
  5.1227 -
  5.1228 -        even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
  5.1229 -        (*_blossom_data)[even].status = MATCHED;
  5.1230 -        evenToMatched(even, tree);
  5.1231 -        (*_blossom_data)[even].next =
  5.1232 -          _graph.oppositeArc((*_blossom_data)[odd].pred);
  5.1233 -      }
  5.1234 -
  5.1235 -    }
  5.1236 -
  5.1237 -    void destroyTree(int tree) {
  5.1238 -      for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
  5.1239 -        if ((*_blossom_data)[b].status == EVEN) {
  5.1240 -          (*_blossom_data)[b].status = MATCHED;
  5.1241 -          evenToMatched(b, tree);
  5.1242 -        } else if ((*_blossom_data)[b].status == ODD) {
  5.1243 -          (*_blossom_data)[b].status = MATCHED;
  5.1244 -          oddToMatched(b);
  5.1245 -        }
  5.1246 -      }
  5.1247 -      _tree_set->eraseClass(tree);
  5.1248 -    }
  5.1249 -
  5.1250 -
  5.1251 -    void unmatchNode(const Node& node) {
  5.1252 -      int blossom = _blossom_set->find(node);
  5.1253 -      int tree = _tree_set->find(blossom);
  5.1254 -
  5.1255 -      alternatePath(blossom, tree);
  5.1256 -      destroyTree(tree);
  5.1257 -
  5.1258 -      (*_blossom_data)[blossom].status = UNMATCHED;
  5.1259 -      (*_blossom_data)[blossom].base = node;
  5.1260 -      matchedToUnmatched(blossom);
  5.1261 -    }
  5.1262 -
  5.1263 -
  5.1264 -    void augmentOnEdge(const Edge& edge) {
  5.1265 -
  5.1266 -      int left = _blossom_set->find(_graph.u(edge));
  5.1267 -      int right = _blossom_set->find(_graph.v(edge));
  5.1268 -
  5.1269 -      if ((*_blossom_data)[left].status == EVEN) {
  5.1270 -        int left_tree = _tree_set->find(left);
  5.1271 -        alternatePath(left, left_tree);
  5.1272 -        destroyTree(left_tree);
  5.1273 -      } else {
  5.1274 -        (*_blossom_data)[left].status = MATCHED;
  5.1275 -        unmatchedToMatched(left);
  5.1276 -      }
  5.1277 -
  5.1278 -      if ((*_blossom_data)[right].status == EVEN) {
  5.1279 -        int right_tree = _tree_set->find(right);
  5.1280 -        alternatePath(right, right_tree);
  5.1281 -        destroyTree(right_tree);
  5.1282 -      } else {
  5.1283 -        (*_blossom_data)[right].status = MATCHED;
  5.1284 -        unmatchedToMatched(right);
  5.1285 -      }
  5.1286 -
  5.1287 -      (*_blossom_data)[left].next = _graph.direct(edge, true);
  5.1288 -      (*_blossom_data)[right].next = _graph.direct(edge, false);
  5.1289 -    }
  5.1290 -
  5.1291 -    void extendOnArc(const Arc& arc) {
  5.1292 -      int base = _blossom_set->find(_graph.target(arc));
  5.1293 -      int tree = _tree_set->find(base);
  5.1294 -
  5.1295 -      int odd = _blossom_set->find(_graph.source(arc));
  5.1296 -      _tree_set->insert(odd, tree);
  5.1297 -      (*_blossom_data)[odd].status = ODD;
  5.1298 -      matchedToOdd(odd);
  5.1299 -      (*_blossom_data)[odd].pred = arc;
  5.1300 -
  5.1301 -      int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
  5.1302 -      (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
  5.1303 -      _tree_set->insert(even, tree);
  5.1304 -      (*_blossom_data)[even].status = EVEN;
  5.1305 -      matchedToEven(even, tree);
  5.1306 -    }
  5.1307 -
  5.1308 -    void shrinkOnEdge(const Edge& edge, int tree) {
  5.1309 -      int nca = -1;
  5.1310 -      std::vector<int> left_path, right_path;
  5.1311 -
  5.1312 -      {
  5.1313 -        std::set<int> left_set, right_set;
  5.1314 -        int left = _blossom_set->find(_graph.u(edge));
  5.1315 -        left_path.push_back(left);
  5.1316 -        left_set.insert(left);
  5.1317 -
  5.1318 -        int right = _blossom_set->find(_graph.v(edge));
  5.1319 -        right_path.push_back(right);
  5.1320 -        right_set.insert(right);
  5.1321 -
  5.1322 -        while (true) {
  5.1323 -
  5.1324 -          if ((*_blossom_data)[left].pred == INVALID) break;
  5.1325 -
  5.1326 -          left =
  5.1327 -            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
  5.1328 -          left_path.push_back(left);
  5.1329 -          left =
  5.1330 -            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
  5.1331 -          left_path.push_back(left);
  5.1332 -
  5.1333 -          left_set.insert(left);
  5.1334 -
  5.1335 -          if (right_set.find(left) != right_set.end()) {
  5.1336 -            nca = left;
  5.1337 -            break;
  5.1338 -          }
  5.1339 -
  5.1340 -          if ((*_blossom_data)[right].pred == INVALID) break;
  5.1341 -
  5.1342 -          right =
  5.1343 -            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
  5.1344 -          right_path.push_back(right);
  5.1345 -          right =
  5.1346 -            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
  5.1347 -          right_path.push_back(right);
  5.1348 -
  5.1349 -          right_set.insert(right);
  5.1350 -
  5.1351 -          if (left_set.find(right) != left_set.end()) {
  5.1352 -            nca = right;
  5.1353 -            break;
  5.1354 -          }
  5.1355 -
  5.1356 -        }
  5.1357 -
  5.1358 -        if (nca == -1) {
  5.1359 -          if ((*_blossom_data)[left].pred == INVALID) {
  5.1360 -            nca = right;
  5.1361 -            while (left_set.find(nca) == left_set.end()) {
  5.1362 -              nca =
  5.1363 -                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  5.1364 -              right_path.push_back(nca);
  5.1365 -              nca =
  5.1366 -                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  5.1367 -              right_path.push_back(nca);
  5.1368 -            }
  5.1369 -          } else {
  5.1370 -            nca = left;
  5.1371 -            while (right_set.find(nca) == right_set.end()) {
  5.1372 -              nca =
  5.1373 -                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  5.1374 -              left_path.push_back(nca);
  5.1375 -              nca =
  5.1376 -                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  5.1377 -              left_path.push_back(nca);
  5.1378 -            }
  5.1379 -          }
  5.1380 -        }
  5.1381 -      }
  5.1382 -
  5.1383 -      std::vector<int> subblossoms;
  5.1384 -      Arc prev;
  5.1385 -
  5.1386 -      prev = _graph.direct(edge, true);
  5.1387 -      for (int i = 0; left_path[i] != nca; i += 2) {
  5.1388 -        subblossoms.push_back(left_path[i]);
  5.1389 -        (*_blossom_data)[left_path[i]].next = prev;
  5.1390 -        _tree_set->erase(left_path[i]);
  5.1391 -
  5.1392 -        subblossoms.push_back(left_path[i + 1]);
  5.1393 -        (*_blossom_data)[left_path[i + 1]].status = EVEN;
  5.1394 -        oddToEven(left_path[i + 1], tree);
  5.1395 -        _tree_set->erase(left_path[i + 1]);
  5.1396 -        prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
  5.1397 -      }
  5.1398 -
  5.1399 -      int k = 0;
  5.1400 -      while (right_path[k] != nca) ++k;
  5.1401 -
  5.1402 -      subblossoms.push_back(nca);
  5.1403 -      (*_blossom_data)[nca].next = prev;
  5.1404 -
  5.1405 -      for (int i = k - 2; i >= 0; i -= 2) {
  5.1406 -        subblossoms.push_back(right_path[i + 1]);
  5.1407 -        (*_blossom_data)[right_path[i + 1]].status = EVEN;
  5.1408 -        oddToEven(right_path[i + 1], tree);
  5.1409 -        _tree_set->erase(right_path[i + 1]);
  5.1410 -
  5.1411 -        (*_blossom_data)[right_path[i + 1]].next =
  5.1412 -          (*_blossom_data)[right_path[i + 1]].pred;
  5.1413 -
  5.1414 -        subblossoms.push_back(right_path[i]);
  5.1415 -        _tree_set->erase(right_path[i]);
  5.1416 -      }
  5.1417 -
  5.1418 -      int surface =
  5.1419 -        _blossom_set->join(subblossoms.begin(), subblossoms.end());
  5.1420 -
  5.1421 -      for (int i = 0; i < int(subblossoms.size()); ++i) {
  5.1422 -        if (!_blossom_set->trivial(subblossoms[i])) {
  5.1423 -          (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
  5.1424 -        }
  5.1425 -        (*_blossom_data)[subblossoms[i]].status = MATCHED;
  5.1426 -      }
  5.1427 -
  5.1428 -      (*_blossom_data)[surface].pot = -2 * _delta_sum;
  5.1429 -      (*_blossom_data)[surface].offset = 0;
  5.1430 -      (*_blossom_data)[surface].status = EVEN;
  5.1431 -      (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
  5.1432 -      (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
  5.1433 -
  5.1434 -      _tree_set->insert(surface, tree);
  5.1435 -      _tree_set->erase(nca);
  5.1436 -    }
  5.1437 -
  5.1438 -    void splitBlossom(int blossom) {
  5.1439 -      Arc next = (*_blossom_data)[blossom].next;
  5.1440 -      Arc pred = (*_blossom_data)[blossom].pred;
  5.1441 -
  5.1442 -      int tree = _tree_set->find(blossom);
  5.1443 -
  5.1444 -      (*_blossom_data)[blossom].status = MATCHED;
  5.1445 -      oddToMatched(blossom);
  5.1446 -      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
  5.1447 -        _delta2->erase(blossom);
  5.1448 -      }
  5.1449 -
  5.1450 -      std::vector<int> subblossoms;
  5.1451 -      _blossom_set->split(blossom, std::back_inserter(subblossoms));
  5.1452 -
  5.1453 -      Value offset = (*_blossom_data)[blossom].offset;
  5.1454 -      int b = _blossom_set->find(_graph.source(pred));
  5.1455 -      int d = _blossom_set->find(_graph.source(next));
  5.1456 -
  5.1457 -      int ib = -1, id = -1;
  5.1458 -      for (int i = 0; i < int(subblossoms.size()); ++i) {
  5.1459 -        if (subblossoms[i] == b) ib = i;
  5.1460 -        if (subblossoms[i] == d) id = i;
  5.1461 -
  5.1462 -        (*_blossom_data)[subblossoms[i]].offset = offset;
  5.1463 -        if (!_blossom_set->trivial(subblossoms[i])) {
  5.1464 -          (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
  5.1465 -        }
  5.1466 -        if (_blossom_set->classPrio(subblossoms[i]) !=
  5.1467 -            std::numeric_limits<Value>::max()) {
  5.1468 -          _delta2->push(subblossoms[i],
  5.1469 -                        _blossom_set->classPrio(subblossoms[i]) -
  5.1470 -                        (*_blossom_data)[subblossoms[i]].offset);
  5.1471 -        }
  5.1472 -      }
  5.1473 -
  5.1474 -      if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
  5.1475 -        for (int i = (id + 1) % subblossoms.size();
  5.1476 -             i != ib; i = (i + 2) % subblossoms.size()) {
  5.1477 -          int sb = subblossoms[i];
  5.1478 -          int tb = subblossoms[(i + 1) % subblossoms.size()];
  5.1479 -          (*_blossom_data)[sb].next =
  5.1480 -            _graph.oppositeArc((*_blossom_data)[tb].next);
  5.1481 -        }
  5.1482 -
  5.1483 -        for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
  5.1484 -          int sb = subblossoms[i];
  5.1485 -          int tb = subblossoms[(i + 1) % subblossoms.size()];
  5.1486 -          int ub = subblossoms[(i + 2) % subblossoms.size()];
  5.1487 -
  5.1488 -          (*_blossom_data)[sb].status = ODD;
  5.1489 -          matchedToOdd(sb);
  5.1490 -          _tree_set->insert(sb, tree);
  5.1491 -          (*_blossom_data)[sb].pred = pred;
  5.1492 -          (*_blossom_data)[sb].next =
  5.1493 -                           _graph.oppositeArc((*_blossom_data)[tb].next);
  5.1494 -
  5.1495 -          pred = (*_blossom_data)[ub].next;
  5.1496 -
  5.1497 -          (*_blossom_data)[tb].status = EVEN;
  5.1498 -          matchedToEven(tb, tree);
  5.1499 -          _tree_set->insert(tb, tree);
  5.1500 -          (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
  5.1501 -        }
  5.1502 -
  5.1503 -        (*_blossom_data)[subblossoms[id]].status = ODD;
  5.1504 -        matchedToOdd(subblossoms[id]);
  5.1505 -        _tree_set->insert(subblossoms[id], tree);
  5.1506 -        (*_blossom_data)[subblossoms[id]].next = next;
  5.1507 -        (*_blossom_data)[subblossoms[id]].pred = pred;
  5.1508 -
  5.1509 -      } else {
  5.1510 -
  5.1511 -        for (int i = (ib + 1) % subblossoms.size();
  5.1512 -             i != id; i = (i + 2) % subblossoms.size()) {
  5.1513 -          int sb = subblossoms[i];
  5.1514 -          int tb = subblossoms[(i + 1) % subblossoms.size()];
  5.1515 -          (*_blossom_data)[sb].next =
  5.1516 -            _graph.oppositeArc((*_blossom_data)[tb].next);
  5.1517 -        }
  5.1518 -
  5.1519 -        for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
  5.1520 -          int sb = subblossoms[i];
  5.1521 -          int tb = subblossoms[(i + 1) % subblossoms.size()];
  5.1522 -          int ub = subblossoms[(i + 2) % subblossoms.size()];
  5.1523 -
  5.1524 -          (*_blossom_data)[sb].status = ODD;
  5.1525 -          matchedToOdd(sb);
  5.1526 -          _tree_set->insert(sb, tree);
  5.1527 -          (*_blossom_data)[sb].next = next;
  5.1528 -          (*_blossom_data)[sb].pred =
  5.1529 -            _graph.oppositeArc((*_blossom_data)[tb].next);
  5.1530 -
  5.1531 -          (*_blossom_data)[tb].status = EVEN;
  5.1532 -          matchedToEven(tb, tree);
  5.1533 -          _tree_set->insert(tb, tree);
  5.1534 -          (*_blossom_data)[tb].pred =
  5.1535 -            (*_blossom_data)[tb].next =
  5.1536 -            _graph.oppositeArc((*_blossom_data)[ub].next);
  5.1537 -          next = (*_blossom_data)[ub].next;
  5.1538 -        }
  5.1539 -
  5.1540 -        (*_blossom_data)[subblossoms[ib]].status = ODD;
  5.1541 -        matchedToOdd(subblossoms[ib]);
  5.1542 -        _tree_set->insert(subblossoms[ib], tree);
  5.1543 -        (*_blossom_data)[subblossoms[ib]].next = next;
  5.1544 -        (*_blossom_data)[subblossoms[ib]].pred = pred;
  5.1545 -      }
  5.1546 -      _tree_set->erase(blossom);
  5.1547 -    }
  5.1548 -
  5.1549 -    void extractBlossom(int blossom, const Node& base, const Arc& matching) {
  5.1550 -      if (_blossom_set->trivial(blossom)) {
  5.1551 -        int bi = (*_node_index)[base];
  5.1552 -        Value pot = (*_node_data)[bi].pot;
  5.1553 -
  5.1554 -        (*_matching)[base] = matching;
  5.1555 -        _blossom_node_list.push_back(base);
  5.1556 -        (*_node_potential)[base] = pot;
  5.1557 -      } else {
  5.1558 -
  5.1559 -        Value pot = (*_blossom_data)[blossom].pot;
  5.1560 -        int bn = _blossom_node_list.size();
  5.1561 -
  5.1562 -        std::vector<int> subblossoms;
  5.1563 -        _blossom_set->split(blossom, std::back_inserter(subblossoms));
  5.1564 -        int b = _blossom_set->find(base);
  5.1565 -        int ib = -1;
  5.1566 -        for (int i = 0; i < int(subblossoms.size()); ++i) {
  5.1567 -          if (subblossoms[i] == b) { ib = i; break; }
  5.1568 -        }
  5.1569 -
  5.1570 -        for (int i = 1; i < int(subblossoms.size()); i += 2) {
  5.1571 -          int sb = subblossoms[(ib + i) % subblossoms.size()];
  5.1572 -          int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
  5.1573 -
  5.1574 -          Arc m = (*_blossom_data)[tb].next;
  5.1575 -          extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
  5.1576 -          extractBlossom(tb, _graph.source(m), m);
  5.1577 -        }
  5.1578 -        extractBlossom(subblossoms[ib], base, matching);
  5.1579 -
  5.1580 -        int en = _blossom_node_list.size();
  5.1581 -
  5.1582 -        _blossom_potential.push_back(BlossomVariable(bn, en, pot));
  5.1583 -      }
  5.1584 -    }
  5.1585 -
  5.1586 -    void extractMatching() {
  5.1587 -      std::vector<int> blossoms;
  5.1588 -      for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
  5.1589 -        blossoms.push_back(c);
  5.1590 -      }
  5.1591 -
  5.1592 -      for (int i = 0; i < int(blossoms.size()); ++i) {
  5.1593 -        if ((*_blossom_data)[blossoms[i]].status == MATCHED) {
  5.1594 -
  5.1595 -          Value offset = (*_blossom_data)[blossoms[i]].offset;
  5.1596 -          (*_blossom_data)[blossoms[i]].pot += 2 * offset;
  5.1597 -          for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
  5.1598 -               n != INVALID; ++n) {
  5.1599 -            (*_node_data)[(*_node_index)[n]].pot -= offset;
  5.1600 -          }
  5.1601 -
  5.1602 -          Arc matching = (*_blossom_data)[blossoms[i]].next;
  5.1603 -          Node base = _graph.source(matching);
  5.1604 -          extractBlossom(blossoms[i], base, matching);
  5.1605 -        } else {
  5.1606 -          Node base = (*_blossom_data)[blossoms[i]].base;
  5.1607 -          extractBlossom(blossoms[i], base, INVALID);
  5.1608 -        }
  5.1609 -      }
  5.1610 -    }
  5.1611 -
  5.1612 -  public:
  5.1613 -
  5.1614 -    /// \brief Constructor
  5.1615 -    ///
  5.1616 -    /// Constructor.
  5.1617 -    MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
  5.1618 -      : _graph(graph), _weight(weight), _matching(0),
  5.1619 -        _node_potential(0), _blossom_potential(), _blossom_node_list(),
  5.1620 -        _node_num(0), _blossom_num(0),
  5.1621 -
  5.1622 -        _blossom_index(0), _blossom_set(0), _blossom_data(0),
  5.1623 -        _node_index(0), _node_heap_index(0), _node_data(0),
  5.1624 -        _tree_set_index(0), _tree_set(0),
  5.1625 -
  5.1626 -        _delta1_index(0), _delta1(0),
  5.1627 -        _delta2_index(0), _delta2(0),
  5.1628 -        _delta3_index(0), _delta3(0),
  5.1629 -        _delta4_index(0), _delta4(0),
  5.1630 -
  5.1631 -        _delta_sum() {}
  5.1632 -
  5.1633 -    ~MaxWeightedMatching() {
  5.1634 -      destroyStructures();
  5.1635 -    }
  5.1636 -
  5.1637 -    /// \name Execution control
  5.1638 -    /// The simplest way to execute the algorithm is to use the
  5.1639 -    /// \c run() member function.
  5.1640 -
  5.1641 -    ///@{
  5.1642 -
  5.1643 -    /// \brief Initialize the algorithm
  5.1644 -    ///
  5.1645 -    /// Initialize the algorithm
  5.1646 -    void init() {
  5.1647 -      createStructures();
  5.1648 -
  5.1649 -      for (ArcIt e(_graph); e != INVALID; ++e) {
  5.1650 -        (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
  5.1651 -      }
  5.1652 -      for (NodeIt n(_graph); n != INVALID; ++n) {
  5.1653 -        (*_delta1_index)[n] = _delta1->PRE_HEAP;
  5.1654 -      }
  5.1655 -      for (EdgeIt e(_graph); e != INVALID; ++e) {
  5.1656 -        (*_delta3_index)[e] = _delta3->PRE_HEAP;
  5.1657 -      }
  5.1658 -      for (int i = 0; i < _blossom_num; ++i) {
  5.1659 -        (*_delta2_index)[i] = _delta2->PRE_HEAP;
  5.1660 -        (*_delta4_index)[i] = _delta4->PRE_HEAP;
  5.1661 -      }
  5.1662 -
  5.1663 -      int index = 0;
  5.1664 -      for (NodeIt n(_graph); n != INVALID; ++n) {
  5.1665 -        Value max = 0;
  5.1666 -        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
  5.1667 -          if (_graph.target(e) == n) continue;
  5.1668 -          if ((dualScale * _weight[e]) / 2 > max) {
  5.1669 -            max = (dualScale * _weight[e]) / 2;
  5.1670 -          }
  5.1671 -        }
  5.1672 -        (*_node_index)[n] = index;
  5.1673 -        (*_node_data)[index].pot = max;
  5.1674 -        _delta1->push(n, max);
  5.1675 -        int blossom =
  5.1676 -          _blossom_set->insert(n, std::numeric_limits<Value>::max());
  5.1677 -
  5.1678 -        _tree_set->insert(blossom);
  5.1679 -
  5.1680 -        (*_blossom_data)[blossom].status = EVEN;
  5.1681 -        (*_blossom_data)[blossom].pred = INVALID;
  5.1682 -        (*_blossom_data)[blossom].next = INVALID;
  5.1683 -        (*_blossom_data)[blossom].pot = 0;
  5.1684 -        (*_blossom_data)[blossom].offset = 0;
  5.1685 -        ++index;
  5.1686 -      }
  5.1687 -      for (EdgeIt e(_graph); e != INVALID; ++e) {
  5.1688 -        int si = (*_node_index)[_graph.u(e)];
  5.1689 -        int ti = (*_node_index)[_graph.v(e)];
  5.1690 -        if (_graph.u(e) != _graph.v(e)) {
  5.1691 -          _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
  5.1692 -                            dualScale * _weight[e]) / 2);
  5.1693 -        }
  5.1694 -      }
  5.1695 -    }
  5.1696 -
  5.1697 -    /// \brief Starts the algorithm
  5.1698 -    ///
  5.1699 -    /// Starts the algorithm
  5.1700 -    void start() {
  5.1701 -      enum OpType {
  5.1702 -        D1, D2, D3, D4
  5.1703 -      };
  5.1704 -
  5.1705 -      int unmatched = _node_num;
  5.1706 -      while (unmatched > 0) {
  5.1707 -        Value d1 = !_delta1->empty() ?
  5.1708 -          _delta1->prio() : std::numeric_limits<Value>::max();
  5.1709 -
  5.1710 -        Value d2 = !_delta2->empty() ?
  5.1711 -          _delta2->prio() : std::numeric_limits<Value>::max();
  5.1712 -
  5.1713 -        Value d3 = !_delta3->empty() ?
  5.1714 -          _delta3->prio() : std::numeric_limits<Value>::max();
  5.1715 -
  5.1716 -        Value d4 = !_delta4->empty() ?
  5.1717 -          _delta4->prio() : std::numeric_limits<Value>::max();
  5.1718 -
  5.1719 -        _delta_sum = d1; OpType ot = D1;
  5.1720 -        if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
  5.1721 -        if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
  5.1722 -        if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
  5.1723 -
  5.1724 -
  5.1725 -        switch (ot) {
  5.1726 -        case D1:
  5.1727 -          {
  5.1728 -            Node n = _delta1->top();
  5.1729 -            unmatchNode(n);
  5.1730 -            --unmatched;
  5.1731 -          }
  5.1732 -          break;
  5.1733 -        case D2:
  5.1734 -          {
  5.1735 -            int blossom = _delta2->top();
  5.1736 -            Node n = _blossom_set->classTop(blossom);
  5.1737 -            Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
  5.1738 -            extendOnArc(e);
  5.1739 -          }
  5.1740 -          break;
  5.1741 -        case D3:
  5.1742 -          {
  5.1743 -            Edge e = _delta3->top();
  5.1744 -
  5.1745 -            int left_blossom = _blossom_set->find(_graph.u(e));
  5.1746 -            int right_blossom = _blossom_set->find(_graph.v(e));
  5.1747 -
  5.1748 -            if (left_blossom == right_blossom) {
  5.1749 -              _delta3->pop();
  5.1750 -            } else {
  5.1751 -              int left_tree;
  5.1752 -              if ((*_blossom_data)[left_blossom].status == EVEN) {
  5.1753 -                left_tree = _tree_set->find(left_blossom);
  5.1754 -              } else {
  5.1755 -                left_tree = -1;
  5.1756 -                ++unmatched;
  5.1757 -              }
  5.1758 -              int right_tree;
  5.1759 -              if ((*_blossom_data)[right_blossom].status == EVEN) {
  5.1760 -                right_tree = _tree_set->find(right_blossom);
  5.1761 -              } else {
  5.1762 -                right_tree = -1;
  5.1763 -                ++unmatched;
  5.1764 -              }
  5.1765 -
  5.1766 -              if (left_tree == right_tree) {
  5.1767 -                shrinkOnEdge(e, left_tree);
  5.1768 -              } else {
  5.1769 -                augmentOnEdge(e);
  5.1770 -                unmatched -= 2;
  5.1771 -              }
  5.1772 -            }
  5.1773 -          } break;
  5.1774 -        case D4:
  5.1775 -          splitBlossom(_delta4->top());
  5.1776 -          break;
  5.1777 -        }
  5.1778 -      }
  5.1779 -      extractMatching();
  5.1780 -    }
  5.1781 -
  5.1782 -    /// \brief Runs %MaxWeightedMatching algorithm.
  5.1783 -    ///
  5.1784 -    /// This method runs the %MaxWeightedMatching algorithm.
  5.1785 -    ///
  5.1786 -    /// \note mwm.run() is just a shortcut of the following code.
  5.1787 -    /// \code
  5.1788 -    ///   mwm.init();
  5.1789 -    ///   mwm.start();
  5.1790 -    /// \endcode
  5.1791 -    void run() {
  5.1792 -      init();
  5.1793 -      start();
  5.1794 -    }
  5.1795 -
  5.1796 -    /// @}
  5.1797 -
  5.1798 -    /// \name Primal solution
  5.1799 -    /// Functions to get the primal solution, ie. the matching.
  5.1800 -
  5.1801 -    /// @{
  5.1802 -
  5.1803 -    /// \brief Returns the weight of the matching.
  5.1804 -    ///
  5.1805 -    /// Returns the weight of the matching.
  5.1806 -    Value matchingValue() const {
  5.1807 -      Value sum = 0;
  5.1808 -      for (NodeIt n(_graph); n != INVALID; ++n) {
  5.1809 -        if ((*_matching)[n] != INVALID) {
  5.1810 -          sum += _weight[(*_matching)[n]];
  5.1811 -        }
  5.1812 -      }
  5.1813 -      return sum /= 2;
  5.1814 -    }
  5.1815 -
  5.1816 -    /// \brief Returns the cardinality of the matching.
  5.1817 -    ///
  5.1818 -    /// Returns the cardinality of the matching.
  5.1819 -    int matchingSize() const {
  5.1820 -      int num = 0;
  5.1821 -      for (NodeIt n(_graph); n != INVALID; ++n) {
  5.1822 -        if ((*_matching)[n] != INVALID) {
  5.1823 -          ++num;
  5.1824 -        }
  5.1825 -      }
  5.1826 -      return num /= 2;
  5.1827 -    }
  5.1828 -
  5.1829 -    /// \brief Returns true when the edge is in the matching.
  5.1830 -    ///
  5.1831 -    /// Returns true when the edge is in the matching.
  5.1832 -    bool matching(const Edge& edge) const {
  5.1833 -      return edge == (*_matching)[_graph.u(edge)];
  5.1834 -    }
  5.1835 -
  5.1836 -    /// \brief Returns the incident matching arc.
  5.1837 -    ///
  5.1838 -    /// Returns the incident matching arc from given node. If the
  5.1839 -    /// node is not matched then it gives back \c INVALID.
  5.1840 -    Arc matching(const Node& node) const {
  5.1841 -      return (*_matching)[node];
  5.1842 -    }
  5.1843 -
  5.1844 -    /// \brief Returns the mate of the node.
  5.1845 -    ///
  5.1846 -    /// Returns the adjancent node in a mathcing arc. If the node is
  5.1847 -    /// not matched then it gives back \c INVALID.
  5.1848 -    Node mate(const Node& node) const {
  5.1849 -      return (*_matching)[node] != INVALID ?
  5.1850 -        _graph.target((*_matching)[node]) : INVALID;
  5.1851 -    }
  5.1852 -
  5.1853 -    /// @}
  5.1854 -
  5.1855 -    /// \name Dual solution
  5.1856 -    /// Functions to get the dual solution.
  5.1857 -
  5.1858 -    /// @{
  5.1859 -
  5.1860 -    /// \brief Returns the value of the dual solution.
  5.1861 -    ///
  5.1862 -    /// Returns the value of the dual solution. It should be equal to
  5.1863 -    /// the primal value scaled by \ref dualScale "dual scale".
  5.1864 -    Value dualValue() const {
  5.1865 -      Value sum = 0;
  5.1866 -      for (NodeIt n(_graph); n != INVALID; ++n) {
  5.1867 -        sum += nodeValue(n);
  5.1868 -      }
  5.1869 -      for (int i = 0; i < blossomNum(); ++i) {
  5.1870 -        sum += blossomValue(i) * (blossomSize(i) / 2);
  5.1871 -      }
  5.1872 -      return sum;
  5.1873 -    }
  5.1874 -
  5.1875 -    /// \brief Returns the value of the node.
  5.1876 -    ///
  5.1877 -    /// Returns the the value of the node.
  5.1878 -    Value nodeValue(const Node& n) const {
  5.1879 -      return (*_node_potential)[n];
  5.1880 -    }
  5.1881 -
  5.1882 -    /// \brief Returns the number of the blossoms in the basis.
  5.1883 -    ///
  5.1884 -    /// Returns the number of the blossoms in the basis.
  5.1885 -    /// \see BlossomIt
  5.1886 -    int blossomNum() const {
  5.1887 -      return _blossom_potential.size();
  5.1888 -    }
  5.1889 -
  5.1890 -
  5.1891 -    /// \brief Returns the number of the nodes in the blossom.
  5.1892 -    ///
  5.1893 -    /// Returns the number of the nodes in the blossom.
  5.1894 -    int blossomSize(int k) const {
  5.1895 -      return _blossom_potential[k].end - _blossom_potential[k].begin;
  5.1896 -    }
  5.1897 -
  5.1898 -    /// \brief Returns the value of the blossom.
  5.1899 -    ///
  5.1900 -    /// Returns the the value of the blossom.
  5.1901 -    /// \see BlossomIt
  5.1902 -    Value blossomValue(int k) const {
  5.1903 -      return _blossom_potential[k].value;
  5.1904 -    }
  5.1905 -
  5.1906 -    /// \brief Iterator for obtaining the nodes of the blossom.
  5.1907 -    ///
  5.1908 -    /// Iterator for obtaining the nodes of the blossom. This class
  5.1909 -    /// provides a common lemon style iterator for listing a
  5.1910 -    /// subset of the nodes.
  5.1911 -    class BlossomIt {
  5.1912 -    public:
  5.1913 -
  5.1914 -      /// \brief Constructor.
  5.1915 -      ///
  5.1916 -      /// Constructor to get the nodes of the variable.
  5.1917 -      BlossomIt(const MaxWeightedMatching& algorithm, int variable)
  5.1918 -        : _algorithm(&algorithm)
  5.1919 -      {
  5.1920 -        _index = _algorithm->_blossom_potential[variable].begin;
  5.1921 -        _last = _algorithm->_blossom_potential[variable].end;
  5.1922 -      }
  5.1923 -
  5.1924 -      /// \brief Conversion to node.
  5.1925 -      ///
  5.1926 -      /// Conversion to node.
  5.1927 -      operator Node() const {
  5.1928 -        return _algorithm->_blossom_node_list[_index];
  5.1929 -      }
  5.1930 -
  5.1931 -      /// \brief Increment operator.
  5.1932 -      ///
  5.1933 -      /// Increment operator.
  5.1934 -      BlossomIt& operator++() {
  5.1935 -        ++_index;
  5.1936 -        return *this;
  5.1937 -      }
  5.1938 -
  5.1939 -      /// \brief Validity checking
  5.1940 -      ///
  5.1941 -      /// Checks whether the iterator is invalid.
  5.1942 -      bool operator==(Invalid) const { return _index == _last; }
  5.1943 -
  5.1944 -      /// \brief Validity checking
  5.1945 -      ///
  5.1946 -      /// Checks whether the iterator is valid.
  5.1947 -      bool operator!=(Invalid) const { return _index != _last; }
  5.1948 -
  5.1949 -    private:
  5.1950 -      const MaxWeightedMatching* _algorithm;
  5.1951 -      int _last;
  5.1952 -      int _index;
  5.1953 -    };
  5.1954 -
  5.1955 -    /// @}
  5.1956 -
  5.1957 -  };
  5.1958 -
  5.1959 -  /// \ingroup matching
  5.1960 -  ///
  5.1961 -  /// \brief Weighted perfect matching in general graphs
  5.1962 -  ///
  5.1963 -  /// This class provides an efficient implementation of Edmond's
  5.1964 -  /// maximum weighted perfect matching algorithm. The implementation
  5.1965 -  /// is based on extensive use of priority queues and provides
  5.1966 -  /// \f$O(nm\log n)\f$ time complexity.
  5.1967 -  ///
  5.1968 -  /// The maximum weighted matching problem is to find undirected
  5.1969 -  /// edges in the graph with maximum overall weight and no two of
  5.1970 -  /// them shares their ends and covers all nodes. The problem can be
  5.1971 -  /// formulated with the following linear program.
  5.1972 -  /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
  5.1973 -  /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
  5.1974 -      \quad \forall B\in\mathcal{O}\f] */
  5.1975 -  /// \f[x_e \ge 0\quad \forall e\in E\f]
  5.1976 -  /// \f[\max \sum_{e\in E}x_ew_e\f]
  5.1977 -  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
  5.1978 -  /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
  5.1979 -  /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
  5.1980 -  /// subsets of the nodes.
  5.1981 -  ///
  5.1982 -  /// The algorithm calculates an optimal matching and a proof of the
  5.1983 -  /// optimality. The solution of the dual problem can be used to check
  5.1984 -  /// the result of the algorithm. The dual linear problem is the
  5.1985 -  /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
  5.1986 -      w_{uv} \quad \forall uv\in E\f] */
  5.1987 -  /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
  5.1988 -  /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
  5.1989 -      \frac{\vert B \vert - 1}{2}z_B\f] */
  5.1990 -  ///
  5.1991 -  /// The algorithm can be executed with \c run() or the \c init() and
  5.1992 -  /// then the \c start() member functions. After it the matching can
  5.1993 -  /// be asked with \c matching() or mate() functions. The dual
  5.1994 -  /// solution can be get with \c nodeValue(), \c blossomNum() and \c
  5.1995 -  /// blossomValue() members and \ref MaxWeightedMatching::BlossomIt
  5.1996 -  /// "BlossomIt" nested class which is able to iterate on the nodes
  5.1997 -  /// of a blossom. If the value type is integral then the dual
  5.1998 -  /// solution is multiplied by \ref MaxWeightedMatching::dualScale "4".
  5.1999 -  template <typename GR,
  5.2000 -            typename WM = typename GR::template EdgeMap<int> >
  5.2001 -  class MaxWeightedPerfectMatching {
  5.2002 -  public:
  5.2003 -
  5.2004 -    typedef GR Graph;
  5.2005 -    typedef WM WeightMap;
  5.2006 -    typedef typename WeightMap::Value Value;
  5.2007 -
  5.2008 -    /// \brief Scaling factor for dual solution
  5.2009 -    ///
  5.2010 -    /// Scaling factor for dual solution, it is equal to 4 or 1
  5.2011 -    /// according to the value type.
  5.2012 -    static const int dualScale =
  5.2013 -      std::numeric_limits<Value>::is_integer ? 4 : 1;
  5.2014 -
  5.2015 -    typedef typename Graph::template NodeMap<typename Graph::Arc>
  5.2016 -    MatchingMap;
  5.2017 -
  5.2018 -  private:
  5.2019 -
  5.2020 -    TEMPLATE_GRAPH_TYPEDEFS(Graph);
  5.2021 -
  5.2022 -    typedef typename Graph::template NodeMap<Value> NodePotential;
  5.2023 -    typedef std::vector<Node> BlossomNodeList;
  5.2024 -
  5.2025 -    struct BlossomVariable {
  5.2026 -      int begin, end;
  5.2027 -      Value value;
  5.2028 -
  5.2029 -      BlossomVariable(int _begin, int _end, Value _value)
  5.2030 -        : begin(_begin), end(_end), value(_value) {}
  5.2031 -
  5.2032 -    };
  5.2033 -
  5.2034 -    typedef std::vector<BlossomVariable> BlossomPotential;
  5.2035 -
  5.2036 -    const Graph& _graph;
  5.2037 -    const WeightMap& _weight;
  5.2038 -
  5.2039 -    MatchingMap* _matching;
  5.2040 -
  5.2041 -    NodePotential* _node_potential;
  5.2042 -
  5.2043 -    BlossomPotential _blossom_potential;
  5.2044 -    BlossomNodeList _blossom_node_list;
  5.2045 -
  5.2046 -    int _node_num;
  5.2047 -    int _blossom_num;
  5.2048 -
  5.2049 -    typedef RangeMap<int> IntIntMap;
  5.2050 -
  5.2051 -    enum Status {
  5.2052 -      EVEN = -1, MATCHED = 0, ODD = 1
  5.2053 -    };
  5.2054 -
  5.2055 -    typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
  5.2056 -    struct BlossomData {
  5.2057 -      int tree;
  5.2058 -      Status status;
  5.2059 -      Arc pred, next;
  5.2060 -      Value pot, offset;
  5.2061 -    };
  5.2062 -
  5.2063 -    IntNodeMap *_blossom_index;
  5.2064 -    BlossomSet *_blossom_set;
  5.2065 -    RangeMap<BlossomData>* _blossom_data;
  5.2066 -
  5.2067 -    IntNodeMap *_node_index;
  5.2068 -    IntArcMap *_node_heap_index;
  5.2069 -
  5.2070 -    struct NodeData {
  5.2071 -
  5.2072 -      NodeData(IntArcMap& node_heap_index)
  5.2073 -        : heap(node_heap_index) {}
  5.2074 -
  5.2075 -      int blossom;
  5.2076 -      Value pot;
  5.2077 -      BinHeap<Value, IntArcMap> heap;
  5.2078 -      std::map<int, Arc> heap_index;
  5.2079 -
  5.2080 -      int tree;
  5.2081 -    };
  5.2082 -
  5.2083 -    RangeMap<NodeData>* _node_data;
  5.2084 -
  5.2085 -    typedef ExtendFindEnum<IntIntMap> TreeSet;
  5.2086 -
  5.2087 -    IntIntMap *_tree_set_index;
  5.2088 -    TreeSet *_tree_set;
  5.2089 -
  5.2090 -    IntIntMap *_delta2_index;
  5.2091 -    BinHeap<Value, IntIntMap> *_delta2;
  5.2092 -
  5.2093 -    IntEdgeMap *_delta3_index;
  5.2094 -    BinHeap<Value, IntEdgeMap> *_delta3;
  5.2095 -
  5.2096 -    IntIntMap *_delta4_index;
  5.2097 -    BinHeap<Value, IntIntMap> *_delta4;
  5.2098 -
  5.2099 -    Value _delta_sum;
  5.2100 -
  5.2101 -    void createStructures() {
  5.2102 -      _node_num = countNodes(_graph);
  5.2103 -      _blossom_num = _node_num * 3 / 2;
  5.2104 -
  5.2105 -      if (!_matching) {
  5.2106 -        _matching = new MatchingMap(_graph);
  5.2107 -      }
  5.2108 -      if (!_node_potential) {
  5.2109 -        _node_potential = new NodePotential(_graph);
  5.2110 -      }
  5.2111 -      if (!_blossom_set) {
  5.2112 -        _blossom_index = new IntNodeMap(_graph);
  5.2113 -        _blossom_set = new BlossomSet(*_blossom_index);
  5.2114 -        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
  5.2115 -      }
  5.2116 -
  5.2117 -      if (!_node_index) {
  5.2118 -        _node_index = new IntNodeMap(_graph);
  5.2119 -        _node_heap_index = new IntArcMap(_graph);
  5.2120 -        _node_data = new RangeMap<NodeData>(_node_num,
  5.2121 -                                            NodeData(*_node_heap_index));
  5.2122 -      }
  5.2123 -
  5.2124 -      if (!_tree_set) {
  5.2125 -        _tree_set_index = new IntIntMap(_blossom_num);
  5.2126 -        _tree_set = new TreeSet(*_tree_set_index);
  5.2127 -      }
  5.2128 -      if (!_delta2) {
  5.2129 -        _delta2_index = new IntIntMap(_blossom_num);
  5.2130 -        _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
  5.2131 -      }
  5.2132 -      if (!_delta3) {
  5.2133 -        _delta3_index = new IntEdgeMap(_graph);
  5.2134 -        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
  5.2135 -      }
  5.2136 -      if (!_delta4) {
  5.2137 -        _delta4_index = new IntIntMap(_blossom_num);
  5.2138 -        _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
  5.2139 -      }
  5.2140 -    }
  5.2141 -
  5.2142 -    void destroyStructures() {
  5.2143 -      _node_num = countNodes(_graph);
  5.2144 -      _blossom_num = _node_num * 3 / 2;
  5.2145 -
  5.2146 -      if (_matching) {
  5.2147 -        delete _matching;
  5.2148 -      }
  5.2149 -      if (_node_potential) {
  5.2150 -        delete _node_potential;
  5.2151 -      }
  5.2152 -      if (_blossom_set) {
  5.2153 -        delete _blossom_index;
  5.2154 -        delete _blossom_set;
  5.2155 -        delete _blossom_data;
  5.2156 -      }
  5.2157 -
  5.2158 -      if (_node_index) {
  5.2159 -        delete _node_index;
  5.2160 -        delete _node_heap_index;
  5.2161 -        delete _node_data;
  5.2162 -      }
  5.2163 -
  5.2164 -      if (_tree_set) {
  5.2165 -        delete _tree_set_index;
  5.2166 -        delete _tree_set;
  5.2167 -      }
  5.2168 -      if (_delta2) {
  5.2169 -        delete _delta2_index;
  5.2170 -        delete _delta2;
  5.2171 -      }
  5.2172 -      if (_delta3) {
  5.2173 -        delete _delta3_index;
  5.2174 -        delete _delta3;
  5.2175 -      }
  5.2176 -      if (_delta4) {
  5.2177 -        delete _delta4_index;
  5.2178 -        delete _delta4;
  5.2179 -      }
  5.2180 -    }
  5.2181 -
  5.2182 -    void matchedToEven(int blossom, int tree) {
  5.2183 -      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
  5.2184 -        _delta2->erase(blossom);
  5.2185 -      }
  5.2186 -
  5.2187 -      if (!_blossom_set->trivial(blossom)) {
  5.2188 -        (*_blossom_data)[blossom].pot -=
  5.2189 -          2 * (_delta_sum - (*_blossom_data)[blossom].offset);
  5.2190 -      }
  5.2191 -
  5.2192 -      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  5.2193 -           n != INVALID; ++n) {
  5.2194 -
  5.2195 -        _blossom_set->increase(n, std::numeric_limits<Value>::max());
  5.2196 -        int ni = (*_node_index)[n];
  5.2197 -
  5.2198 -        (*_node_data)[ni].heap.clear();
  5.2199 -        (*_node_data)[ni].heap_index.clear();
  5.2200 -
  5.2201 -        (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
  5.2202 -
  5.2203 -        for (InArcIt e(_graph, n); e != INVALID; ++e) {
  5.2204 -          Node v = _graph.source(e);
  5.2205 -          int vb = _blossom_set->find(v);
  5.2206 -          int vi = (*_node_index)[v];
  5.2207 -
  5.2208 -          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  5.2209 -            dualScale * _weight[e];
  5.2210 -
  5.2211 -          if ((*_blossom_data)[vb].status == EVEN) {
  5.2212 -            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
  5.2213 -              _delta3->push(e, rw / 2);
  5.2214 -            }
  5.2215 -          } else {
  5.2216 -            typename std::map<int, Arc>::iterator it =
  5.2217 -              (*_node_data)[vi].heap_index.find(tree);
  5.2218 -
  5.2219 -            if (it != (*_node_data)[vi].heap_index.end()) {
  5.2220 -              if ((*_node_data)[vi].heap[it->second] > rw) {
  5.2221 -                (*_node_data)[vi].heap.replace(it->second, e);
  5.2222 -                (*_node_data)[vi].heap.decrease(e, rw);
  5.2223 -                it->second = e;
  5.2224 -              }
  5.2225 -            } else {
  5.2226 -              (*_node_data)[vi].heap.push(e, rw);
  5.2227 -              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
  5.2228 -            }
  5.2229 -
  5.2230 -            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
  5.2231 -              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
  5.2232 -
  5.2233 -              if ((*_blossom_data)[vb].status == MATCHED) {
  5.2234 -                if (_delta2->state(vb) != _delta2->IN_HEAP) {
  5.2235 -                  _delta2->push(vb, _blossom_set->classPrio(vb) -
  5.2236 -                               (*_blossom_data)[vb].offset);
  5.2237 -                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
  5.2238 -                           (*_blossom_data)[vb].offset){
  5.2239 -                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
  5.2240 -                                   (*_blossom_data)[vb].offset);
  5.2241 -                }
  5.2242 -              }
  5.2243 -            }
  5.2244 -          }
  5.2245 -        }
  5.2246 -      }
  5.2247 -      (*_blossom_data)[blossom].offset = 0;
  5.2248 -    }
  5.2249 -
  5.2250 -    void matchedToOdd(int blossom) {
  5.2251 -      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
  5.2252 -        _delta2->erase(blossom);
  5.2253 -      }
  5.2254 -      (*_blossom_data)[blossom].offset += _delta_sum;
  5.2255 -      if (!_blossom_set->trivial(blossom)) {
  5.2256 -        _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
  5.2257 -                     (*_blossom_data)[blossom].offset);
  5.2258 -      }
  5.2259 -    }
  5.2260 -
  5.2261 -    void evenToMatched(int blossom, int tree) {
  5.2262 -      if (!_blossom_set->trivial(blossom)) {
  5.2263 -        (*_blossom_data)[blossom].pot += 2 * _delta_sum;
  5.2264 -      }
  5.2265 -
  5.2266 -      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  5.2267 -           n != INVALID; ++n) {
  5.2268 -        int ni = (*_node_index)[n];
  5.2269 -        (*_node_data)[ni].pot -= _delta_sum;
  5.2270 -
  5.2271 -        for (InArcIt e(_graph, n); e != INVALID; ++e) {
  5.2272 -          Node v = _graph.source(e);
  5.2273 -          int vb = _blossom_set->find(v);
  5.2274 -          int vi = (*_node_index)[v];
  5.2275 -
  5.2276 -          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  5.2277 -            dualScale * _weight[e];
  5.2278 -
  5.2279 -          if (vb == blossom) {
  5.2280 -            if (_delta3->state(e) == _delta3->IN_HEAP) {
  5.2281 -              _delta3->erase(e);
  5.2282 -            }
  5.2283 -          } else if ((*_blossom_data)[vb].status == EVEN) {
  5.2284 -
  5.2285 -            if (_delta3->state(e) == _delta3->IN_HEAP) {
  5.2286 -              _delta3->erase(e);
  5.2287 -            }
  5.2288 -
  5.2289 -            int vt = _tree_set->find(vb);
  5.2290 -
  5.2291 -            if (vt != tree) {
  5.2292 -
  5.2293 -              Arc r = _graph.oppositeArc(e);
  5.2294 -
  5.2295 -              typename std::map<int, Arc>::iterator it =
  5.2296 -                (*_node_data)[ni].heap_index.find(vt);
  5.2297 -
  5.2298 -              if (it != (*_node_data)[ni].heap_index.end()) {
  5.2299 -                if ((*_node_data)[ni].heap[it->second] > rw) {
  5.2300 -                  (*_node_data)[ni].heap.replace(it->second, r);
  5.2301 -                  (*_node_data)[ni].heap.decrease(r, rw);
  5.2302 -                  it->second = r;
  5.2303 -                }
  5.2304 -              } else {
  5.2305 -                (*_node_data)[ni].heap.push(r, rw);
  5.2306 -                (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
  5.2307 -              }
  5.2308 -
  5.2309 -              if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
  5.2310 -                _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
  5.2311 -
  5.2312 -                if (_delta2->state(blossom) != _delta2->IN_HEAP) {
  5.2313 -                  _delta2->push(blossom, _blossom_set->classPrio(blossom) -
  5.2314 -                               (*_blossom_data)[blossom].offset);
  5.2315 -                } else if ((*_delta2)[blossom] >
  5.2316 -                           _blossom_set->classPrio(blossom) -
  5.2317 -                           (*_blossom_data)[blossom].offset){
  5.2318 -                  _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
  5.2319 -                                   (*_blossom_data)[blossom].offset);
  5.2320 -                }
  5.2321 -              }
  5.2322 -            }
  5.2323 -          } else {
  5.2324 -
  5.2325 -            typename std::map<int, Arc>::iterator it =
  5.2326 -              (*_node_data)[vi].heap_index.find(tree);
  5.2327 -
  5.2328 -            if (it != (*_node_data)[vi].heap_index.end()) {
  5.2329 -              (*_node_data)[vi].heap.erase(it->second);
  5.2330 -              (*_node_data)[vi].heap_index.erase(it);
  5.2331 -              if ((*_node_data)[vi].heap.empty()) {
  5.2332 -                _blossom_set->increase(v, std::numeric_limits<Value>::max());
  5.2333 -              } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
  5.2334 -                _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
  5.2335 -              }
  5.2336 -
  5.2337 -              if ((*_blossom_data)[vb].status == MATCHED) {
  5.2338 -                if (_blossom_set->classPrio(vb) ==
  5.2339 -                    std::numeric_limits<Value>::max()) {
  5.2340 -                  _delta2->erase(vb);
  5.2341 -                } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
  5.2342 -                           (*_blossom_data)[vb].offset) {
  5.2343 -                  _delta2->increase(vb, _blossom_set->classPrio(vb) -
  5.2344 -                                   (*_blossom_data)[vb].offset);
  5.2345 -                }
  5.2346 -              }
  5.2347 -            }
  5.2348 -          }
  5.2349 -        }
  5.2350 -      }
  5.2351 -    }
  5.2352 -
  5.2353 -    void oddToMatched(int blossom) {
  5.2354 -      (*_blossom_data)[blossom].offset -= _delta_sum;
  5.2355 -
  5.2356 -      if (_blossom_set->classPrio(blossom) !=
  5.2357 -          std::numeric_limits<Value>::max()) {
  5.2358 -        _delta2->push(blossom, _blossom_set->classPrio(blossom) -
  5.2359 -                       (*_blossom_data)[blossom].offset);
  5.2360 -      }
  5.2361 -
  5.2362 -      if (!_blossom_set->trivial(blossom)) {
  5.2363 -        _delta4->erase(blossom);
  5.2364 -      }
  5.2365 -    }
  5.2366 -
  5.2367 -    void oddToEven(int blossom, int tree) {
  5.2368 -      if (!_blossom_set->trivial(blossom)) {
  5.2369 -        _delta4->erase(blossom);
  5.2370 -        (*_blossom_data)[blossom].pot -=
  5.2371 -          2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
  5.2372 -      }
  5.2373 -
  5.2374 -      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  5.2375 -           n != INVALID; ++n) {
  5.2376 -        int ni = (*_node_index)[n];
  5.2377 -
  5.2378 -        _blossom_set->increase(n, std::numeric_limits<Value>::max());
  5.2379 -
  5.2380 -        (*_node_data)[ni].heap.clear();
  5.2381 -        (*_node_data)[ni].heap_index.clear();
  5.2382 -        (*_node_data)[ni].pot +=
  5.2383 -          2 * _delta_sum - (*_blossom_data)[blossom].offset;
  5.2384 -
  5.2385 -        for (InArcIt e(_graph, n); e != INVALID; ++e) {
  5.2386 -          Node v = _graph.source(e);
  5.2387 -          int vb = _blossom_set->find(v);
  5.2388 -          int vi = (*_node_index)[v];
  5.2389 -
  5.2390 -          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  5.2391 -            dualScale * _weight[e];
  5.2392 -
  5.2393 -          if ((*_blossom_data)[vb].status == EVEN) {
  5.2394 -            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
  5.2395 -              _delta3->push(e, rw / 2);
  5.2396 -            }
  5.2397 -          } else {
  5.2398 -
  5.2399 -            typename std::map<int, Arc>::iterator it =
  5.2400 -              (*_node_data)[vi].heap_index.find(tree);
  5.2401 -
  5.2402 -            if (it != (*_node_data)[vi].heap_index.end()) {
  5.2403 -              if ((*_node_data)[vi].heap[it->second] > rw) {
  5.2404 -                (*_node_data)[vi].heap.replace(it->second, e);
  5.2405 -                (*_node_data)[vi].heap.decrease(e, rw);
  5.2406 -                it->second = e;
  5.2407 -              }
  5.2408 -            } else {
  5.2409 -              (*_node_data)[vi].heap.push(e, rw);
  5.2410 -              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
  5.2411 -            }
  5.2412 -
  5.2413 -            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
  5.2414 -              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
  5.2415 -
  5.2416 -              if ((*_blossom_data)[vb].status == MATCHED) {
  5.2417 -                if (_delta2->state(vb) != _delta2->IN_HEAP) {
  5.2418 -                  _delta2->push(vb, _blossom_set->classPrio(vb) -
  5.2419 -                               (*_blossom_data)[vb].offset);
  5.2420 -                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
  5.2421 -                           (*_blossom_data)[vb].offset) {
  5.2422 -                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
  5.2423 -                                   (*_blossom_data)[vb].offset);
  5.2424 -                }
  5.2425 -              }
  5.2426 -            }
  5.2427 -          }
  5.2428 -        }
  5.2429 -      }
  5.2430 -      (*_blossom_data)[blossom].offset = 0;
  5.2431 -    }
  5.2432 -
  5.2433 -    void alternatePath(int even, int tree) {
  5.2434 -      int odd;
  5.2435 -
  5.2436 -      evenToMatched(even, tree);
  5.2437 -      (*_blossom_data)[even].status = MATCHED;
  5.2438 -
  5.2439 -      while ((*_blossom_data)[even].pred != INVALID) {
  5.2440 -        odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
  5.2441 -        (*_blossom_data)[odd].status = MATCHED;
  5.2442 -        oddToMatched(odd);
  5.2443 -        (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
  5.2444 -
  5.2445 -        even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
  5.2446 -        (*_blossom_data)[even].status = MATCHED;
  5.2447 -        evenToMatched(even, tree);
  5.2448 -        (*_blossom_data)[even].next =
  5.2449 -          _graph.oppositeArc((*_blossom_data)[odd].pred);
  5.2450 -      }
  5.2451 -
  5.2452 -    }
  5.2453 -
  5.2454 -    void destroyTree(int tree) {
  5.2455 -      for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
  5.2456 -        if ((*_blossom_data)[b].status == EVEN) {
  5.2457 -          (*_blossom_data)[b].status = MATCHED;
  5.2458 -          evenToMatched(b, tree);
  5.2459 -        } else if ((*_blossom_data)[b].status == ODD) {
  5.2460 -          (*_blossom_data)[b].status = MATCHED;
  5.2461 -          oddToMatched(b);
  5.2462 -        }
  5.2463 -      }
  5.2464 -      _tree_set->eraseClass(tree);
  5.2465 -    }
  5.2466 -
  5.2467 -    void augmentOnEdge(const Edge& edge) {
  5.2468 -
  5.2469 -      int left = _blossom_set->find(_graph.u(edge));
  5.2470 -      int right = _blossom_set->find(_graph.v(edge));
  5.2471 -
  5.2472 -      int left_tree = _tree_set->find(left);
  5.2473 -      alternatePath(left, left_tree);
  5.2474 -      destroyTree(left_tree);
  5.2475 -
  5.2476 -      int right_tree = _tree_set->find(right);
  5.2477 -      alternatePath(right, right_tree);
  5.2478 -      destroyTree(right_tree);
  5.2479 -
  5.2480 -      (*_blossom_data)[left].next = _graph.direct(edge, true);
  5.2481 -      (*_blossom_data)[right].next = _graph.direct(edge, false);
  5.2482 -    }
  5.2483 -
  5.2484 -    void extendOnArc(const Arc& arc) {
  5.2485 -      int base = _blossom_set->find(_graph.target(arc));
  5.2486 -      int tree = _tree_set->find(base);
  5.2487 -
  5.2488 -      int odd = _blossom_set->find(_graph.source(arc));
  5.2489 -      _tree_set->insert(odd, tree);
  5.2490 -      (*_blossom_data)[odd].status = ODD;
  5.2491 -      matchedToOdd(odd);
  5.2492 -      (*_blossom_data)[odd].pred = arc;
  5.2493 -
  5.2494 -      int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
  5.2495 -      (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
  5.2496 -      _tree_set->insert(even, tree);
  5.2497 -      (*_blossom_data)[even].status = EVEN;
  5.2498 -      matchedToEven(even, tree);
  5.2499 -    }
  5.2500 -
  5.2501 -    void shrinkOnEdge(const Edge& edge, int tree) {
  5.2502 -      int nca = -1;
  5.2503 -      std::vector<int> left_path, right_path;
  5.2504 -
  5.2505 -      {
  5.2506 -        std::set<int> left_set, right_set;
  5.2507 -        int left = _blossom_set->find(_graph.u(edge));
  5.2508 -        left_path.push_back(left);
  5.2509 -        left_set.insert(left);
  5.2510 -
  5.2511 -        int right = _blossom_set->find(_graph.v(edge));
  5.2512 -        right_path.push_back(right);
  5.2513 -        right_set.insert(right);
  5.2514 -
  5.2515 -        while (true) {
  5.2516 -
  5.2517 -          if ((*_blossom_data)[left].pred == INVALID) break;
  5.2518 -
  5.2519 -          left =
  5.2520 -            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
  5.2521 -          left_path.push_back(left);
  5.2522 -          left =
  5.2523 -            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
  5.2524 -          left_path.push_back(left);
  5.2525 -
  5.2526 -          left_set.insert(left);
  5.2527 -
  5.2528 -          if (right_set.find(left) != right_set.end()) {
  5.2529 -            nca = left;
  5.2530 -            break;
  5.2531 -          }
  5.2532 -
  5.2533 -          if ((*_blossom_data)[right].pred == INVALID) break;
  5.2534 -
  5.2535 -          right =
  5.2536 -            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
  5.2537 -          right_path.push_back(right);
  5.2538 -          right =
  5.2539 -            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
  5.2540 -          right_path.push_back(right);
  5.2541 -
  5.2542 -          right_set.insert(right);
  5.2543 -
  5.2544 -          if (left_set.find(right) != left_set.end()) {
  5.2545 -            nca = right;
  5.2546 -            break;
  5.2547 -          }
  5.2548 -
  5.2549 -        }
  5.2550 -
  5.2551 -        if (nca == -1) {
  5.2552 -          if ((*_blossom_data)[left].pred == INVALID) {
  5.2553 -            nca = right;
  5.2554 -            while (left_set.find(nca) == left_set.end()) {
  5.2555 -              nca =
  5.2556 -                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  5.2557 -              right_path.push_back(nca);
  5.2558 -              nca =
  5.2559 -                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  5.2560 -              right_path.push_back(nca);
  5.2561 -            }
  5.2562 -          } else {
  5.2563 -            nca = left;
  5.2564 -            while (right_set.find(nca) == right_set.end()) {
  5.2565 -              nca =
  5.2566 -                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  5.2567 -              left_path.push_back(nca);
  5.2568 -              nca =
  5.2569 -                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  5.2570 -              left_path.push_back(nca);
  5.2571 -            }
  5.2572 -          }
  5.2573 -        }
  5.2574 -      }
  5.2575 -
  5.2576 -      std::vector<int> subblossoms;
  5.2577 -      Arc prev;
  5.2578 -
  5.2579 -      prev = _graph.direct(edge, true);
  5.2580 -      for (int i = 0; left_path[i] != nca; i += 2) {
  5.2581 -        subblossoms.push_back(left_path[i]);
  5.2582 -        (*_blossom_data)[left_path[i]].next = prev;
  5.2583 -        _tree_set->erase(left_path[i]);
  5.2584 -
  5.2585 -        subblossoms.push_back(left_path[i + 1]);
  5.2586 -        (*_blossom_data)[left_path[i + 1]].status = EVEN;
  5.2587 -        oddToEven(left_path[i + 1], tree);
  5.2588 -        _tree_set->erase(left_path[i + 1]);
  5.2589 -        prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
  5.2590 -      }
  5.2591 -
  5.2592 -      int k = 0;
  5.2593 -      while (right_path[k] != nca) ++k;
  5.2594 -
  5.2595 -      subblossoms.push_back(nca);
  5.2596 -      (*_blossom_data)[nca].next = prev;
  5.2597 -
  5.2598 -      for (int i = k - 2; i >= 0; i -= 2) {
  5.2599 -        subblossoms.push_back(right_path[i + 1]);
  5.2600 -        (*_blossom_data)[right_path[i + 1]].status = EVEN;
  5.2601 -        oddToEven(right_path[i + 1], tree);
  5.2602 -        _tree_set->erase(right_path[i + 1]);
  5.2603 -
  5.2604 -        (*_blossom_data)[right_path[i + 1]].next =
  5.2605 -          (*_blossom_data)[right_path[i + 1]].pred;
  5.2606 -
  5.2607 -        subblossoms.push_back(right_path[i]);
  5.2608 -        _tree_set->erase(right_path[i]);
  5.2609 -      }
  5.2610 -
  5.2611 -      int surface =
  5.2612 -        _blossom_set->join(subblossoms.begin(), subblossoms.end());
  5.2613 -
  5.2614 -      for (int i = 0; i < int(subblossoms.size()); ++i) {
  5.2615 -        if (!_blossom_set->trivial(subblossoms[i])) {
  5.2616 -          (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
  5.2617 -        }
  5.2618 -        (*_blossom_data)[subblossoms[i]].status = MATCHED;
  5.2619 -      }
  5.2620 -
  5.2621 -      (*_blossom_data)[surface].pot = -2 * _delta_sum;
  5.2622 -      (*_blossom_data)[surface].offset = 0;
  5.2623 -      (*_blossom_data)[surface].status = EVEN;
  5.2624 -      (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
  5.2625 -      (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
  5.2626 -
  5.2627 -      _tree_set->insert(surface, tree);
  5.2628 -      _tree_set->erase(nca);
  5.2629 -    }
  5.2630 -
  5.2631 -    void splitBlossom(int blossom) {
  5.2632 -      Arc next = (*_blossom_data)[blossom].next;
  5.2633 -      Arc pred = (*_blossom_data)[blossom].pred;
  5.2634 -
  5.2635 -      int tree = _tree_set->find(blossom);
  5.2636 -
  5.2637 -      (*_blossom_data)[blossom].status = MATCHED;
  5.2638 -      oddToMatched(blossom);
  5.2639 -      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
  5.2640 -        _delta2->erase(blossom);
  5.2641 -      }
  5.2642 -
  5.2643 -      std::vector<int> subblossoms;
  5.2644 -      _blossom_set->split(blossom, std::back_inserter(subblossoms));
  5.2645 -
  5.2646 -      Value offset = (*_blossom_data)[blossom].offset;
  5.2647 -      int b = _blossom_set->find(_graph.source(pred));
  5.2648 -      int d = _blossom_set->find(_graph.source(next));
  5.2649 -
  5.2650 -      int ib = -1, id = -1;
  5.2651 -      for (int i = 0; i < int(subblossoms.size()); ++i) {
  5.2652 -        if (subblossoms[i] == b) ib = i;
  5.2653 -        if (subblossoms[i] == d) id = i;
  5.2654 -
  5.2655 -        (*_blossom_data)[subblossoms[i]].offset = offset;
  5.2656 -        if (!_blossom_set->trivial(subblossoms[i])) {
  5.2657 -          (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
  5.2658 -        }
  5.2659 -        if (_blossom_set->classPrio(subblossoms[i]) !=
  5.2660 -            std::numeric_limits<Value>::max()) {
  5.2661 -          _delta2->push(subblossoms[i],
  5.2662 -                        _blossom_set->classPrio(subblossoms[i]) -
  5.2663 -                        (*_blossom_data)[subblossoms[i]].offset);
  5.2664 -        }
  5.2665 -      }
  5.2666 -
  5.2667 -      if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
  5.2668 -        for (int i = (id + 1) % subblossoms.size();
  5.2669 -             i != ib; i = (i + 2) % subblossoms.size()) {
  5.2670 -          int sb = subblossoms[i];
  5.2671 -          int tb = subblossoms[(i + 1) % subblossoms.size()];
  5.2672 -          (*_blossom_data)[sb].next =
  5.2673 -            _graph.oppositeArc((*_blossom_data)[tb].next);
  5.2674 -        }
  5.2675 -
  5.2676 -        for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
  5.2677 -          int sb = subblossoms[i];
  5.2678 -          int tb = subblossoms[(i + 1) % subblossoms.size()];
  5.2679 -          int ub = subblossoms[(i + 2) % subblossoms.size()];
  5.2680 -
  5.2681 -          (*_blossom_data)[sb].status = ODD;
  5.2682 -          matchedToOdd(sb);
  5.2683 -          _tree_set->insert(sb, tree);
  5.2684 -          (*_blossom_data)[sb].pred = pred;
  5.2685 -          (*_blossom_data)[sb].next =
  5.2686 -                           _graph.oppositeArc((*_blossom_data)[tb].next);
  5.2687 -
  5.2688 -          pred = (*_blossom_data)[ub].next;
  5.2689 -
  5.2690 -          (*_blossom_data)[tb].status = EVEN;
  5.2691 -          matchedToEven(tb, tree);
  5.2692 -          _tree_set->insert(tb, tree);
  5.2693 -          (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
  5.2694 -        }
  5.2695 -
  5.2696 -        (*_blossom_data)[subblossoms[id]].status = ODD;
  5.2697 -        matchedToOdd(subblossoms[id]);
  5.2698 -        _tree_set->insert(subblossoms[id], tree);
  5.2699 -        (*_blossom_data)[subblossoms[id]].next = next;
  5.2700 -        (*_blossom_data)[subblossoms[id]].pred = pred;
  5.2701 -
  5.2702 -      } else {
  5.2703 -
  5.2704 -        for (int i = (ib + 1) % subblossoms.size();
  5.2705 -             i != id; i = (i + 2) % subblossoms.size()) {
  5.2706 -          int sb = subblossoms[i];
  5.2707 -          int tb = subblossoms[(i + 1) % subblossoms.size()];
  5.2708 -          (*_blossom_data)[sb].next =
  5.2709 -            _graph.oppositeArc((*_blossom_data)[tb].next);
  5.2710 -        }
  5.2711 -
  5.2712 -        for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
  5.2713 -          int sb = subblossoms[i];
  5.2714 -          int tb = subblossoms[(i + 1) % subblossoms.size()];
  5.2715 -          int ub = subblossoms[(i + 2) % subblossoms.size()];
  5.2716 -
  5.2717 -          (*_blossom_data)[sb].status = ODD;
  5.2718 -          matchedToOdd(sb);
  5.2719 -          _tree_set->insert(sb, tree);
  5.2720 -          (*_blossom_data)[sb].next = next;
  5.2721 -          (*_blossom_data)[sb].pred =
  5.2722 -            _graph.oppositeArc((*_blossom_data)[tb].next);
  5.2723 -
  5.2724 -          (*_blossom_data)[tb].status = EVEN;
  5.2725 -          matchedToEven(tb, tree);
  5.2726 -          _tree_set->insert(tb, tree);
  5.2727 -          (*_blossom_data)[tb].pred =
  5.2728 -            (*_blossom_data)[tb].next =
  5.2729 -            _graph.oppositeArc((*_blossom_data)[ub].next);
  5.2730 -          next = (*_blossom_data)[ub].next;
  5.2731 -        }
  5.2732 -
  5.2733 -        (*_blossom_data)[subblossoms[ib]].status = ODD;
  5.2734 -        matchedToOdd(subblossoms[ib]);
  5.2735 -        _tree_set->insert(subblossoms[ib], tree);
  5.2736 -        (*_blossom_data)[subblossoms[ib]].next = next;
  5.2737 -        (*_blossom_data)[subblossoms[ib]].pred = pred;
  5.2738 -      }
  5.2739 -      _tree_set->erase(blossom);
  5.2740 -    }
  5.2741 -
  5.2742 -    void extractBlossom(int blossom, const Node& base, const Arc& matching) {
  5.2743 -      if (_blossom_set->trivial(blossom)) {
  5.2744 -        int bi = (*_node_index)[base];
  5.2745 -        Value pot = (*_node_data)[bi].pot;
  5.2746 -
  5.2747 -        (*_matching)[base] = matching;
  5.2748 -        _blossom_node_list.push_back(base);
  5.2749 -        (*_node_potential)[base] = pot;
  5.2750 -      } else {
  5.2751 -
  5.2752 -        Value pot = (*_blossom_data)[blossom].pot;
  5.2753 -        int bn = _blossom_node_list.size();
  5.2754 -
  5.2755 -        std::vector<int> subblossoms;
  5.2756 -        _blossom_set->split(blossom, std::back_inserter(subblossoms));
  5.2757 -        int b = _blossom_set->find(base);
  5.2758 -        int ib = -1;
  5.2759 -        for (int i = 0; i < int(subblossoms.size()); ++i) {
  5.2760 -          if (subblossoms[i] == b) { ib = i; break; }
  5.2761 -        }
  5.2762 -
  5.2763 -        for (int i = 1; i < int(subblossoms.size()); i += 2) {
  5.2764 -          int sb = subblossoms[(ib + i) % subblossoms.size()];
  5.2765 -          int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
  5.2766 -
  5.2767 -          Arc m = (*_blossom_data)[tb].next;
  5.2768 -          extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
  5.2769 -          extractBlossom(tb, _graph.source(m), m);
  5.2770 -        }
  5.2771 -        extractBlossom(subblossoms[ib], base, matching);
  5.2772 -
  5.2773 -        int en = _blossom_node_list.size();
  5.2774 -
  5.2775 -        _blossom_potential.push_back(BlossomVariable(bn, en, pot));
  5.2776 -      }
  5.2777 -    }
  5.2778 -
  5.2779 -    void extractMatching() {
  5.2780 -      std::vector<int> blossoms;
  5.2781 -      for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
  5.2782 -        blossoms.push_back(c);
  5.2783 -      }
  5.2784 -
  5.2785 -      for (int i = 0; i < int(blossoms.size()); ++i) {
  5.2786 -
  5.2787 -        Value offset = (*_blossom_data)[blossoms[i]].offset;
  5.2788 -        (*_blossom_data)[blossoms[i]].pot += 2 * offset;
  5.2789 -        for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
  5.2790 -             n != INVALID; ++n) {
  5.2791 -          (*_node_data)[(*_node_index)[n]].pot -= offset;
  5.2792 -        }
  5.2793 -
  5.2794 -        Arc matching = (*_blossom_data)[blossoms[i]].next;
  5.2795 -        Node base = _graph.source(matching);
  5.2796 -        extractBlossom(blossoms[i], base, matching);
  5.2797 -      }
  5.2798 -    }
  5.2799 -
  5.2800 -  public:
  5.2801 -
  5.2802 -    /// \brief Constructor
  5.2803 -    ///
  5.2804 -    /// Constructor.
  5.2805 -    MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
  5.2806 -      : _graph(graph), _weight(weight), _matching(0),
  5.2807 -        _node_potential(0), _blossom_potential(), _blossom_node_list(),
  5.2808 -        _node_num(0), _blossom_num(0),
  5.2809 -
  5.2810 -        _blossom_index(0), _blossom_set(0), _blossom_data(0),
  5.2811 -        _node_index(0), _node_heap_index(0), _node_data(0),
  5.2812 -        _tree_set_index(0), _tree_set(0),
  5.2813 -
  5.2814 -        _delta2_index(0), _delta2(0),
  5.2815 -        _delta3_index(0), _delta3(0),
  5.2816 -        _delta4_index(0), _delta4(0),
  5.2817 -
  5.2818 -        _delta_sum() {}
  5.2819 -
  5.2820 -    ~MaxWeightedPerfectMatching() {
  5.2821 -      destroyStructures();
  5.2822 -    }
  5.2823 -
  5.2824 -    /// \name Execution control
  5.2825 -    /// The simplest way to execute the algorithm is to use the
  5.2826 -    /// \c run() member function.
  5.2827 -
  5.2828 -    ///@{
  5.2829 -
  5.2830 -    /// \brief Initialize the algorithm
  5.2831 -    ///
  5.2832 -    /// Initialize the algorithm
  5.2833 -    void init() {
  5.2834 -      createStructures();
  5.2835 -
  5.2836 -      for (ArcIt e(_graph); e != INVALID; ++e) {
  5.2837 -        (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
  5.2838 -      }
  5.2839 -      for (EdgeIt e(_graph); e != INVALID; ++e) {
  5.2840 -        (*_delta3_index)[e] = _delta3->PRE_HEAP;
  5.2841 -      }
  5.2842 -      for (int i = 0; i < _blossom_num; ++i) {
  5.2843 -        (*_delta2_index)[i] = _delta2->PRE_HEAP;
  5.2844 -        (*_delta4_index)[i] = _delta4->PRE_HEAP;
  5.2845 -      }
  5.2846 -
  5.2847 -      int index = 0;
  5.2848 -      for (NodeIt n(_graph); n != INVALID; ++n) {
  5.2849 -        Value max = - std::numeric_limits<Value>::max();
  5.2850 -        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
  5.2851 -          if (_graph.target(e) == n) continue;
  5.2852 -          if ((dualScale * _weight[e]) / 2 > max) {
  5.2853 -            max = (dualScale * _weight[e]) / 2;
  5.2854 -          }
  5.2855 -        }
  5.2856 -        (*_node_index)[n] = index;
  5.2857 -        (*_node_data)[index].pot = max;
  5.2858 -        int blossom =
  5.2859 -          _blossom_set->insert(n, std::numeric_limits<Value>::max());
  5.2860 -
  5.2861 -        _tree_set->insert(blossom);
  5.2862 -
  5.2863 -        (*_blossom_data)[blossom].status = EVEN;
  5.2864 -        (*_blossom_data)[blossom].pred = INVALID;
  5.2865 -        (*_blossom_data)[blossom].next = INVALID;
  5.2866 -        (*_blossom_data)[blossom].pot = 0;
  5.2867 -        (*_blossom_data)[blossom].offset = 0;
  5.2868 -        ++index;
  5.2869 -      }
  5.2870 -      for (EdgeIt e(_graph); e != INVALID; ++e) {
  5.2871 -        int si = (*_node_index)[_graph.u(e)];
  5.2872 -        int ti = (*_node_index)[_graph.v(e)];
  5.2873 -        if (_graph.u(e) != _graph.v(e)) {
  5.2874 -          _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
  5.2875 -                            dualScale * _weight[e]) / 2);
  5.2876 -        }
  5.2877 -      }
  5.2878 -    }
  5.2879 -
  5.2880 -    /// \brief Starts the algorithm
  5.2881 -    ///
  5.2882 -    /// Starts the algorithm
  5.2883 -    bool start() {
  5.2884 -      enum OpType {
  5.2885 -        D2, D3, D4
  5.2886 -      };
  5.2887 -
  5.2888 -      int unmatched = _node_num;
  5.2889 -      while (unmatched > 0) {
  5.2890 -        Value d2 = !_delta2->empty() ?
  5.2891 -          _delta2->prio() : std::numeric_limits<Value>::max();
  5.2892 -
  5.2893 -        Value d3 = !_delta3->empty() ?
  5.2894 -          _delta3->prio() : std::numeric_limits<Value>::max();
  5.2895 -
  5.2896 -        Value d4 = !_delta4->empty() ?
  5.2897 -          _delta4->prio() : std::numeric_limits<Value>::max();
  5.2898 -
  5.2899 -        _delta_sum = d2; OpType ot = D2;
  5.2900 -        if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
  5.2901 -        if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
  5.2902 -
  5.2903 -        if (_delta_sum == std::numeric_limits<Value>::max()) {
  5.2904 -          return false;
  5.2905 -        }
  5.2906 -
  5.2907 -        switch (ot) {
  5.2908 -        case D2:
  5.2909 -          {
  5.2910 -            int blossom = _delta2->top();
  5.2911 -            Node n = _blossom_set->classTop(blossom);
  5.2912 -            Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
  5.2913 -            extendOnArc(e);
  5.2914 -          }
  5.2915 -          break;
  5.2916 -        case D3:
  5.2917 -          {
  5.2918 -            Edge e = _delta3->top();
  5.2919 -
  5.2920 -            int left_blossom = _blossom_set->find(_graph.u(e));
  5.2921 -            int right_blossom = _blossom_set->find(_graph.v(e));
  5.2922 -
  5.2923 -            if (left_blossom == right_blossom) {
  5.2924 -              _delta3->pop();
  5.2925 -            } else {
  5.2926 -              int left_tree = _tree_set->find(left_blossom);
  5.2927 -              int right_tree = _tree_set->find(right_blossom);
  5.2928 -
  5.2929 -              if (left_tree == right_tree) {
  5.2930 -                shrinkOnEdge(e, left_tree);
  5.2931 -              } else {
  5.2932 -                augmentOnEdge(e);
  5.2933 -                unmatched -= 2;
  5.2934 -              }
  5.2935 -            }
  5.2936 -          } break;
  5.2937 -        case D4:
  5.2938 -          splitBlossom(_delta4->top());
  5.2939 -          break;
  5.2940 -        }
  5.2941 -      }
  5.2942 -      extractMatching();
  5.2943 -      return true;
  5.2944 -    }
  5.2945 -
  5.2946 -    /// \brief Runs %MaxWeightedPerfectMatching algorithm.
  5.2947 -    ///
  5.2948 -    /// This method runs the %MaxWeightedPerfectMatching algorithm.
  5.2949 -    ///
  5.2950 -    /// \note mwm.run() is just a shortcut of the following code.
  5.2951 -    /// \code
  5.2952 -    ///   mwm.init();
  5.2953 -    ///   mwm.start();
  5.2954 -    /// \endcode
  5.2955 -    bool run() {
  5.2956 -      init();
  5.2957 -      return start();
  5.2958 -    }
  5.2959 -
  5.2960 -    /// @}
  5.2961 -
  5.2962 -    /// \name Primal solution
  5.2963 -    /// Functions to get the primal solution, ie. the matching.
  5.2964 -
  5.2965 -    /// @{
  5.2966 -
  5.2967 -    /// \brief Returns the matching value.
  5.2968 -    ///
  5.2969 -    /// Returns the matching value.
  5.2970 -    Value matchingValue() const {
  5.2971 -      Value sum = 0;
  5.2972 -      for (NodeIt n(_graph); n != INVALID; ++n) {
  5.2973 -        if ((*_matching)[n] != INVALID) {
  5.2974 -          sum += _weight[(*_matching)[n]];
  5.2975 -        }
  5.2976 -      }
  5.2977 -      return sum /= 2;
  5.2978 -    }
  5.2979 -
  5.2980 -    /// \brief Returns true when the edge is in the matching.
  5.2981 -    ///
  5.2982 -    /// Returns true when the edge is in the matching.
  5.2983 -    bool matching(const Edge& edge) const {
  5.2984 -      return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
  5.2985 -    }
  5.2986 -
  5.2987 -    /// \brief Returns the incident matching edge.
  5.2988 -    ///
  5.2989 -    /// Returns the incident matching arc from given edge.
  5.2990 -    Arc matching(const Node& node) const {
  5.2991 -      return (*_matching)[node];
  5.2992 -    }
  5.2993 -
  5.2994 -    /// \brief Returns the mate of the node.
  5.2995 -    ///
  5.2996 -    /// Returns the adjancent node in a mathcing arc.
  5.2997 -    Node mate(const Node& node) const {
  5.2998 -      return _graph.target((*_matching)[node]);
  5.2999 -    }
  5.3000 -
  5.3001 -    /// @}
  5.3002 -
  5.3003 -    /// \name Dual solution
  5.3004 -    /// Functions to get the dual solution.
  5.3005 -
  5.3006 -    /// @{
  5.3007 -
  5.3008 -    /// \brief Returns the value of the dual solution.
  5.3009 -    ///
  5.3010 -    /// Returns the value of the dual solution. It should be equal to
  5.3011 -    /// the primal value scaled by \ref dualScale "dual scale".
  5.3012 -    Value dualValue() const {
  5.3013 -      Value sum = 0;
  5.3014 -      for (NodeIt n(_graph); n != INVALID; ++n) {
  5.3015 -        sum += nodeValue(n);
  5.3016 -      }
  5.3017 -      for (int i = 0; i < blossomNum(); ++i) {
  5.3018 -        sum += blossomValue(i) * (blossomSize(i) / 2);
  5.3019 -      }
  5.3020 -      return sum;
  5.3021 -    }
  5.3022 -
  5.3023 -    /// \brief Returns the value of the node.
  5.3024 -    ///
  5.3025 -    /// Returns the the value of the node.
  5.3026 -    Value nodeValue(const Node& n) const {
  5.3027 -      return (*_node_potential)[n];
  5.3028 -    }
  5.3029 -
  5.3030 -    /// \brief Returns the number of the blossoms in the basis.
  5.3031 -    ///
  5.3032 -    /// Returns the number of the blossoms in the basis.
  5.3033 -    /// \see BlossomIt
  5.3034 -    int blossomNum() const {
  5.3035 -      return _blossom_potential.size();
  5.3036 -    }
  5.3037 -
  5.3038 -
  5.3039 -    /// \brief Returns the number of the nodes in the blossom.
  5.3040 -    ///
  5.3041 -    /// Returns the number of the nodes in the blossom.
  5.3042 -    int blossomSize(int k) const {
  5.3043 -      return _blossom_potential[k].end - _blossom_potential[k].begin;
  5.3044 -    }
  5.3045 -
  5.3046 -    /// \brief Returns the value of the blossom.
  5.3047 -    ///
  5.3048 -    /// Returns the the value of the blossom.
  5.3049 -    /// \see BlossomIt
  5.3050 -    Value blossomValue(int k) const {
  5.3051 -      return _blossom_potential[k].value;
  5.3052 -    }
  5.3053 -
  5.3054 -    /// \brief Iterator for obtaining the nodes of the blossom.
  5.3055 -    ///
  5.3056 -    /// Iterator for obtaining the nodes of the blossom. This class
  5.3057 -    /// provides a common lemon style iterator for listing a
  5.3058 -    /// subset of the nodes.
  5.3059 -    class BlossomIt {
  5.3060 -    public:
  5.3061 -
  5.3062 -      /// \brief Constructor.
  5.3063 -      ///
  5.3064 -      /// Constructor to get the nodes of the variable.
  5.3065 -      BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
  5.3066 -        : _algorithm(&algorithm)
  5.3067 -      {
  5.3068 -        _index = _algorithm->_blossom_potential[variable].begin;
  5.3069 -        _last = _algorithm->_blossom_potential[variable].end;
  5.3070 -      }
  5.3071 -
  5.3072 -      /// \brief Conversion to node.
  5.3073 -      ///
  5.3074 -      /// Conversion to node.
  5.3075 -      operator Node() const {
  5.3076 -        return _algorithm->_blossom_node_list[_index];
  5.3077 -      }
  5.3078 -
  5.3079 -      /// \brief Increment operator.
  5.3080 -      ///
  5.3081 -      /// Increment operator.
  5.3082 -      BlossomIt& operator++() {
  5.3083 -        ++_index;
  5.3084 -        return *this;
  5.3085 -      }
  5.3086 -
  5.3087 -      /// \brief Validity checking
  5.3088 -      ///
  5.3089 -      /// Checks whether the iterator is invalid.
  5.3090 -      bool operator==(Invalid) const { return _index == _last; }
  5.3091 -
  5.3092 -      /// \brief Validity checking
  5.3093 -      ///
  5.3094 -      /// Checks whether the iterator is valid.
  5.3095 -      bool operator!=(Invalid) const { return _index != _last; }
  5.3096 -
  5.3097 -    private:
  5.3098 -      const MaxWeightedPerfectMatching* _algorithm;
  5.3099 -      int _last;
  5.3100 -      int _index;
  5.3101 -    };
  5.3102 -
  5.3103 -    /// @}
  5.3104 -
  5.3105 -  };
  5.3106 -
  5.3107 -
  5.3108 -} //END OF NAMESPACE LEMON
  5.3109 -
  5.3110 -#endif //LEMON_MAX_MATCHING_H
     6.1 --- a/test/CMakeLists.txt	Tue Apr 21 10:34:49 2009 +0100
     6.2 +++ b/test/CMakeLists.txt	Tue Apr 21 13:08:19 2009 +0100
     6.3 @@ -29,7 +29,7 @@
     6.4    heap_test
     6.5    kruskal_test
     6.6    maps_test
     6.7 -  max_matching_test
     6.8 +  matching_test
     6.9    min_cost_arborescence_test
    6.10    path_test
    6.11    preflow_test
     7.1 --- a/test/Makefile.am	Tue Apr 21 10:34:49 2009 +0100
     7.2 +++ b/test/Makefile.am	Tue Apr 21 13:08:19 2009 +0100
     7.3 @@ -25,7 +25,7 @@
     7.4  	test/heap_test \
     7.5  	test/kruskal_test \
     7.6  	test/maps_test \
     7.7 -	test/max_matching_test \
     7.8 +	test/matching_test \
     7.9  	test/min_cost_arborescence_test \
    7.10  	test/path_test \
    7.11  	test/preflow_test \
    7.12 @@ -70,7 +70,7 @@
    7.13  test_lp_test_SOURCES = test/lp_test.cc
    7.14  test_maps_test_SOURCES = test/maps_test.cc
    7.15  test_mip_test_SOURCES = test/mip_test.cc
    7.16 -test_max_matching_test_SOURCES = test/max_matching_test.cc
    7.17 +test_matching_test_SOURCES = test/matching_test.cc
    7.18  test_min_cost_arborescence_test_SOURCES = test/min_cost_arborescence_test.cc
    7.19  test_path_test_SOURCES = test/path_test.cc
    7.20  test_preflow_test_SOURCES = test/preflow_test.cc
     8.1 --- a/test/euler_test.cc	Tue Apr 21 10:34:49 2009 +0100
     8.2 +++ b/test/euler_test.cc	Tue Apr 21 13:08:19 2009 +0100
     8.3 @@ -18,136 +18,206 @@
     8.4  
     8.5  #include <lemon/euler.h>
     8.6  #include <lemon/list_graph.h>
     8.7 -#include <test/test_tools.h>
     8.8 +#include <lemon/adaptors.h>
     8.9 +#include "test_tools.h"
    8.10  
    8.11  using namespace lemon;
    8.12  
    8.13  template <typename Digraph>
    8.14 -void checkDiEulerIt(const Digraph& g)
    8.15 +void checkDiEulerIt(const Digraph& g,
    8.16 +                    const typename Digraph::Node& start = INVALID)
    8.17  {
    8.18    typename Digraph::template ArcMap<int> visitationNumber(g, 0);
    8.19  
    8.20 -  DiEulerIt<Digraph> e(g);
    8.21 +  DiEulerIt<Digraph> e(g, start);
    8.22 +  if (e == INVALID) return;
    8.23    typename Digraph::Node firstNode = g.source(e);
    8.24    typename Digraph::Node lastNode = g.target(e);
    8.25 +  if (start != INVALID) {
    8.26 +    check(firstNode == start, "checkDiEulerIt: Wrong first node");
    8.27 +  }
    8.28  
    8.29 -  for (; e != INVALID; ++e)
    8.30 -  {
    8.31 -    if (e != INVALID)
    8.32 -    {
    8.33 -      lastNode = g.target(e);
    8.34 -    }
    8.35 +  for (; e != INVALID; ++e) {
    8.36 +    if (e != INVALID) lastNode = g.target(e);
    8.37      ++visitationNumber[e];
    8.38    }
    8.39  
    8.40    check(firstNode == lastNode,
    8.41 -      "checkDiEulerIt: first and last node are not the same");
    8.42 +      "checkDiEulerIt: First and last nodes are not the same");
    8.43  
    8.44    for (typename Digraph::ArcIt a(g); a != INVALID; ++a)
    8.45    {
    8.46      check(visitationNumber[a] == 1,
    8.47 -        "checkDiEulerIt: not visited or multiple times visited arc found");
    8.48 +        "checkDiEulerIt: Not visited or multiple times visited arc found");
    8.49    }
    8.50  }
    8.51  
    8.52  template <typename Graph>
    8.53 -void checkEulerIt(const Graph& g)
    8.54 +void checkEulerIt(const Graph& g,
    8.55 +                  const typename Graph::Node& start = INVALID)
    8.56  {
    8.57    typename Graph::template EdgeMap<int> visitationNumber(g, 0);
    8.58  
    8.59 -  EulerIt<Graph> e(g);
    8.60 -  typename Graph::Node firstNode = g.u(e);
    8.61 -  typename Graph::Node lastNode = g.v(e);
    8.62 +  EulerIt<Graph> e(g, start);
    8.63 +  if (e == INVALID) return;
    8.64 +  typename Graph::Node firstNode = g.source(typename Graph::Arc(e));
    8.65 +  typename Graph::Node lastNode = g.target(typename Graph::Arc(e));
    8.66 +  if (start != INVALID) {
    8.67 +    check(firstNode == start, "checkEulerIt: Wrong first node");
    8.68 +  }
    8.69  
    8.70 -  for (; e != INVALID; ++e)
    8.71 -  {
    8.72 -    if (e != INVALID)
    8.73 -    {
    8.74 -      lastNode = g.v(e);
    8.75 -    }
    8.76 +  for (; e != INVALID; ++e) {
    8.77 +    if (e != INVALID) lastNode = g.target(typename Graph::Arc(e));
    8.78      ++visitationNumber[e];
    8.79    }
    8.80  
    8.81    check(firstNode == lastNode,
    8.82 -      "checkEulerIt: first and last node are not the same");
    8.83 +      "checkEulerIt: First and last nodes are not the same");
    8.84  
    8.85    for (typename Graph::EdgeIt e(g); e != INVALID; ++e)
    8.86    {
    8.87      check(visitationNumber[e] == 1,
    8.88 -        "checkEulerIt: not visited or multiple times visited edge found");
    8.89 +        "checkEulerIt: Not visited or multiple times visited edge found");
    8.90    }
    8.91  }
    8.92  
    8.93  int main()
    8.94  {
    8.95    typedef ListDigraph Digraph;
    8.96 -  typedef ListGraph Graph;
    8.97 +  typedef Undirector<Digraph> Graph;
    8.98 +  
    8.99 +  {
   8.100 +    Digraph d;
   8.101 +    Graph g(d);
   8.102 +    
   8.103 +    checkDiEulerIt(d);
   8.104 +    checkDiEulerIt(g);
   8.105 +    checkEulerIt(g);
   8.106  
   8.107 -  Digraph digraphWithEulerianCircuit;
   8.108 +    check(eulerian(d), "This graph is Eulerian");
   8.109 +    check(eulerian(g), "This graph is Eulerian");
   8.110 +  }
   8.111    {
   8.112 -    Digraph& g = digraphWithEulerianCircuit;
   8.113 +    Digraph d;
   8.114 +    Graph g(d);
   8.115 +    Digraph::Node n = d.addNode();
   8.116  
   8.117 -    Digraph::Node n0 = g.addNode();
   8.118 -    Digraph::Node n1 = g.addNode();
   8.119 -    Digraph::Node n2 = g.addNode();
   8.120 +    checkDiEulerIt(d);
   8.121 +    checkDiEulerIt(g);
   8.122 +    checkEulerIt(g);
   8.123  
   8.124 -    g.addArc(n0, n1);
   8.125 -    g.addArc(n1, n0);
   8.126 -    g.addArc(n1, n2);
   8.127 -    g.addArc(n2, n1);
   8.128 +    check(eulerian(d), "This graph is Eulerian");
   8.129 +    check(eulerian(g), "This graph is Eulerian");
   8.130    }
   8.131 +  {
   8.132 +    Digraph d;
   8.133 +    Graph g(d);
   8.134 +    Digraph::Node n = d.addNode();
   8.135 +    d.addArc(n, n);
   8.136  
   8.137 -  Digraph digraphWithoutEulerianCircuit;
   8.138 +    checkDiEulerIt(d);
   8.139 +    checkDiEulerIt(g);
   8.140 +    checkEulerIt(g);
   8.141 +
   8.142 +    check(eulerian(d), "This graph is Eulerian");
   8.143 +    check(eulerian(g), "This graph is Eulerian");
   8.144 +  }
   8.145    {
   8.146 -    Digraph& g = digraphWithoutEulerianCircuit;
   8.147 +    Digraph d;
   8.148 +    Graph g(d);
   8.149 +    Digraph::Node n1 = d.addNode();
   8.150 +    Digraph::Node n2 = d.addNode();
   8.151 +    Digraph::Node n3 = d.addNode();
   8.152 +    
   8.153 +    d.addArc(n1, n2);
   8.154 +    d.addArc(n2, n1);
   8.155 +    d.addArc(n2, n3);
   8.156 +    d.addArc(n3, n2);
   8.157  
   8.158 -    Digraph::Node n0 = g.addNode();
   8.159 -    Digraph::Node n1 = g.addNode();
   8.160 -    Digraph::Node n2 = g.addNode();
   8.161 +    checkDiEulerIt(d);
   8.162 +    checkDiEulerIt(d, n2);
   8.163 +    checkDiEulerIt(g);
   8.164 +    checkDiEulerIt(g, n2);
   8.165 +    checkEulerIt(g);
   8.166 +    checkEulerIt(g, n2);
   8.167  
   8.168 -    g.addArc(n0, n1);
   8.169 -    g.addArc(n1, n0);
   8.170 -    g.addArc(n1, n2);
   8.171 +    check(eulerian(d), "This graph is Eulerian");
   8.172 +    check(eulerian(g), "This graph is Eulerian");
   8.173    }
   8.174 +  {
   8.175 +    Digraph d;
   8.176 +    Graph g(d);
   8.177 +    Digraph::Node n1 = d.addNode();
   8.178 +    Digraph::Node n2 = d.addNode();
   8.179 +    Digraph::Node n3 = d.addNode();
   8.180 +    Digraph::Node n4 = d.addNode();
   8.181 +    Digraph::Node n5 = d.addNode();
   8.182 +    Digraph::Node n6 = d.addNode();
   8.183 +    
   8.184 +    d.addArc(n1, n2);
   8.185 +    d.addArc(n2, n4);
   8.186 +    d.addArc(n1, n3);
   8.187 +    d.addArc(n3, n4);
   8.188 +    d.addArc(n4, n1);
   8.189 +    d.addArc(n3, n5);
   8.190 +    d.addArc(n5, n2);
   8.191 +    d.addArc(n4, n6);
   8.192 +    d.addArc(n2, n6);
   8.193 +    d.addArc(n6, n1);
   8.194 +    d.addArc(n6, n3);
   8.195  
   8.196 -  Graph graphWithEulerianCircuit;
   8.197 +    checkDiEulerIt(d);
   8.198 +    checkDiEulerIt(d, n1);
   8.199 +    checkDiEulerIt(d, n5);
   8.200 +
   8.201 +    checkDiEulerIt(g);
   8.202 +    checkDiEulerIt(g, n1);
   8.203 +    checkDiEulerIt(g, n5);
   8.204 +    checkEulerIt(g);
   8.205 +    checkEulerIt(g, n1);
   8.206 +    checkEulerIt(g, n5);
   8.207 +
   8.208 +    check(eulerian(d), "This graph is Eulerian");
   8.209 +    check(eulerian(g), "This graph is Eulerian");
   8.210 +  }
   8.211    {
   8.212 -    Graph& g = graphWithEulerianCircuit;
   8.213 +    Digraph d;
   8.214 +    Graph g(d);
   8.215 +    Digraph::Node n0 = d.addNode();
   8.216 +    Digraph::Node n1 = d.addNode();
   8.217 +    Digraph::Node n2 = d.addNode();
   8.218 +    Digraph::Node n3 = d.addNode();
   8.219 +    Digraph::Node n4 = d.addNode();
   8.220 +    Digraph::Node n5 = d.addNode();
   8.221 +    
   8.222 +    d.addArc(n1, n2);
   8.223 +    d.addArc(n2, n3);
   8.224 +    d.addArc(n3, n1);
   8.225  
   8.226 -    Graph::Node n0 = g.addNode();
   8.227 -    Graph::Node n1 = g.addNode();
   8.228 -    Graph::Node n2 = g.addNode();
   8.229 +    checkDiEulerIt(d);
   8.230 +    checkDiEulerIt(d, n2);
   8.231  
   8.232 -    g.addEdge(n0, n1);
   8.233 -    g.addEdge(n1, n2);
   8.234 -    g.addEdge(n2, n0);
   8.235 +    checkDiEulerIt(g);
   8.236 +    checkDiEulerIt(g, n2);
   8.237 +    checkEulerIt(g);
   8.238 +    checkEulerIt(g, n2);
   8.239 +
   8.240 +    check(!eulerian(d), "This graph is not Eulerian");
   8.241 +    check(!eulerian(g), "This graph is not Eulerian");
   8.242    }
   8.243 +  {
   8.244 +    Digraph d;
   8.245 +    Graph g(d);
   8.246 +    Digraph::Node n1 = d.addNode();
   8.247 +    Digraph::Node n2 = d.addNode();
   8.248 +    Digraph::Node n3 = d.addNode();
   8.249 +    
   8.250 +    d.addArc(n1, n2);
   8.251 +    d.addArc(n2, n3);
   8.252  
   8.253 -  Graph graphWithoutEulerianCircuit;
   8.254 -  {
   8.255 -    Graph& g = graphWithoutEulerianCircuit;
   8.256 -
   8.257 -    Graph::Node n0 = g.addNode();
   8.258 -    Graph::Node n1 = g.addNode();
   8.259 -    Graph::Node n2 = g.addNode();
   8.260 -
   8.261 -    g.addEdge(n0, n1);
   8.262 -    g.addEdge(n1, n2);
   8.263 +    check(!eulerian(d), "This graph is not Eulerian");
   8.264 +    check(!eulerian(g), "This graph is not Eulerian");
   8.265    }
   8.266  
   8.267 -  checkDiEulerIt(digraphWithEulerianCircuit);
   8.268 -
   8.269 -  checkEulerIt(graphWithEulerianCircuit);
   8.270 -
   8.271 -  check(eulerian(digraphWithEulerianCircuit),
   8.272 -      "this graph should have an Eulerian circuit");
   8.273 -  check(!eulerian(digraphWithoutEulerianCircuit),
   8.274 -      "this graph should not have an Eulerian circuit");
   8.275 -
   8.276 -  check(eulerian(graphWithEulerianCircuit),
   8.277 -      "this graph should have an Eulerian circuit");
   8.278 -  check(!eulerian(graphWithoutEulerianCircuit),
   8.279 -      "this graph should have an Eulerian circuit");
   8.280 -
   8.281    return 0;
   8.282  }
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/test/matching_test.cc	Tue Apr 21 13:08:19 2009 +0100
     9.3 @@ -0,0 +1,424 @@
     9.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
     9.5 + *
     9.6 + * This file is a part of LEMON, a generic C++ optimization library.
     9.7 + *
     9.8 + * Copyright (C) 2003-2009
     9.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
    9.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
    9.11 + *
    9.12 + * Permission to use, modify and distribute this software is granted
    9.13 + * provided that this copyright notice appears in all copies. For
    9.14 + * precise terms see the accompanying LICENSE file.
    9.15 + *
    9.16 + * This software is provided "AS IS" with no warranty of any kind,
    9.17 + * express or implied, and with no claim as to its suitability for any
    9.18 + * purpose.
    9.19 + *
    9.20 + */
    9.21 +
    9.22 +#include <iostream>
    9.23 +#include <sstream>
    9.24 +#include <vector>
    9.25 +#include <queue>
    9.26 +#include <cstdlib>
    9.27 +
    9.28 +#include <lemon/matching.h>
    9.29 +#include <lemon/smart_graph.h>
    9.30 +#include <lemon/concepts/graph.h>
    9.31 +#include <lemon/concepts/maps.h>
    9.32 +#include <lemon/lgf_reader.h>
    9.33 +#include <lemon/math.h>
    9.34 +
    9.35 +#include "test_tools.h"
    9.36 +
    9.37 +using namespace std;
    9.38 +using namespace lemon;
    9.39 +
    9.40 +GRAPH_TYPEDEFS(SmartGraph);
    9.41 +
    9.42 +
    9.43 +const int lgfn = 3;
    9.44 +const std::string lgf[lgfn] = {
    9.45 +  "@nodes\n"
    9.46 +  "label\n"
    9.47 +  "0\n"
    9.48 +  "1\n"
    9.49 +  "2\n"
    9.50 +  "3\n"
    9.51 +  "4\n"
    9.52 +  "5\n"
    9.53 +  "6\n"
    9.54 +  "7\n"
    9.55 +  "@edges\n"
    9.56 +  "     label  weight\n"
    9.57 +  "7 4  0      984\n"
    9.58 +  "0 7  1      73\n"
    9.59 +  "7 1  2      204\n"
    9.60 +  "2 3  3      583\n"
    9.61 +  "2 7  4      565\n"
    9.62 +  "2 1  5      582\n"
    9.63 +  "0 4  6      551\n"
    9.64 +  "2 5  7      385\n"
    9.65 +  "1 5  8      561\n"
    9.66 +  "5 3  9      484\n"
    9.67 +  "7 5  10     904\n"
    9.68 +  "3 6  11     47\n"
    9.69 +  "7 6  12     888\n"
    9.70 +  "3 0  13     747\n"
    9.71 +  "6 1  14     310\n",
    9.72 +
    9.73 +  "@nodes\n"
    9.74 +  "label\n"
    9.75 +  "0\n"
    9.76 +  "1\n"
    9.77 +  "2\n"
    9.78 +  "3\n"
    9.79 +  "4\n"
    9.80 +  "5\n"
    9.81 +  "6\n"
    9.82 +  "7\n"
    9.83 +  "@edges\n"
    9.84 +  "     label  weight\n"
    9.85 +  "2 5  0      710\n"
    9.86 +  "0 5  1      241\n"
    9.87 +  "2 4  2      856\n"
    9.88 +  "2 6  3      762\n"
    9.89 +  "4 1  4      747\n"
    9.90 +  "6 1  5      962\n"
    9.91 +  "4 7  6      723\n"
    9.92 +  "1 7  7      661\n"
    9.93 +  "2 3  8      376\n"
    9.94 +  "1 0  9      416\n"
    9.95 +  "6 7  10     391\n",
    9.96 +
    9.97 +  "@nodes\n"
    9.98 +  "label\n"
    9.99 +  "0\n"
   9.100 +  "1\n"
   9.101 +  "2\n"
   9.102 +  "3\n"
   9.103 +  "4\n"
   9.104 +  "5\n"
   9.105 +  "6\n"
   9.106 +  "7\n"
   9.107 +  "@edges\n"
   9.108 +  "     label  weight\n"
   9.109 +  "6 2  0      553\n"
   9.110 +  "0 7  1      653\n"
   9.111 +  "6 3  2      22\n"
   9.112 +  "4 7  3      846\n"
   9.113 +  "7 2  4      981\n"
   9.114 +  "7 6  5      250\n"
   9.115 +  "5 2  6      539\n",
   9.116 +};
   9.117 +
   9.118 +void checkMaxMatchingCompile()
   9.119 +{
   9.120 +  typedef concepts::Graph Graph;
   9.121 +  typedef Graph::Node Node;
   9.122 +  typedef Graph::Edge Edge;
   9.123 +  typedef Graph::EdgeMap<bool> MatMap;
   9.124 +
   9.125 +  Graph g;
   9.126 +  Node n;
   9.127 +  Edge e;
   9.128 +  MatMap mat(g);
   9.129 +
   9.130 +  MaxMatching<Graph> mat_test(g);
   9.131 +  const MaxMatching<Graph>&
   9.132 +    const_mat_test = mat_test;
   9.133 +
   9.134 +  mat_test.init();
   9.135 +  mat_test.greedyInit();
   9.136 +  mat_test.matchingInit(mat);
   9.137 +  mat_test.startSparse();
   9.138 +  mat_test.startDense();
   9.139 +  mat_test.run();
   9.140 +  
   9.141 +  const_mat_test.matchingSize();
   9.142 +  const_mat_test.matching(e);
   9.143 +  const_mat_test.matching(n);
   9.144 +  const MaxMatching<Graph>::MatchingMap& mmap =
   9.145 +    const_mat_test.matchingMap();
   9.146 +  e = mmap[n];
   9.147 +  const_mat_test.mate(n);
   9.148 +
   9.149 +  MaxMatching<Graph>::Status stat = 
   9.150 +    const_mat_test.status(n);
   9.151 +  const MaxMatching<Graph>::StatusMap& smap =
   9.152 +    const_mat_test.statusMap();
   9.153 +  stat = smap[n];
   9.154 +  const_mat_test.barrier(n);
   9.155 +}
   9.156 +
   9.157 +void checkMaxWeightedMatchingCompile()
   9.158 +{
   9.159 +  typedef concepts::Graph Graph;
   9.160 +  typedef Graph::Node Node;
   9.161 +  typedef Graph::Edge Edge;
   9.162 +  typedef Graph::EdgeMap<int> WeightMap;
   9.163 +
   9.164 +  Graph g;
   9.165 +  Node n;
   9.166 +  Edge e;
   9.167 +  WeightMap w(g);
   9.168 +
   9.169 +  MaxWeightedMatching<Graph> mat_test(g, w);
   9.170 +  const MaxWeightedMatching<Graph>&
   9.171 +    const_mat_test = mat_test;
   9.172 +
   9.173 +  mat_test.init();
   9.174 +  mat_test.start();
   9.175 +  mat_test.run();
   9.176 +  
   9.177 +  const_mat_test.matchingWeight();
   9.178 +  const_mat_test.matchingSize();
   9.179 +  const_mat_test.matching(e);
   9.180 +  const_mat_test.matching(n);
   9.181 +  const MaxWeightedMatching<Graph>::MatchingMap& mmap =
   9.182 +    const_mat_test.matchingMap();
   9.183 +  e = mmap[n];
   9.184 +  const_mat_test.mate(n);
   9.185 +  
   9.186 +  int k = 0;
   9.187 +  const_mat_test.dualValue();
   9.188 +  const_mat_test.nodeValue(n);
   9.189 +  const_mat_test.blossomNum();
   9.190 +  const_mat_test.blossomSize(k);
   9.191 +  const_mat_test.blossomValue(k);
   9.192 +}
   9.193 +
   9.194 +void checkMaxWeightedPerfectMatchingCompile()
   9.195 +{
   9.196 +  typedef concepts::Graph Graph;
   9.197 +  typedef Graph::Node Node;
   9.198 +  typedef Graph::Edge Edge;
   9.199 +  typedef Graph::EdgeMap<int> WeightMap;
   9.200 +
   9.201 +  Graph g;
   9.202 +  Node n;
   9.203 +  Edge e;
   9.204 +  WeightMap w(g);
   9.205 +
   9.206 +  MaxWeightedPerfectMatching<Graph> mat_test(g, w);
   9.207 +  const MaxWeightedPerfectMatching<Graph>&
   9.208 +    const_mat_test = mat_test;
   9.209 +
   9.210 +  mat_test.init();
   9.211 +  mat_test.start();
   9.212 +  mat_test.run();
   9.213 +  
   9.214 +  const_mat_test.matchingWeight();
   9.215 +  const_mat_test.matching(e);
   9.216 +  const_mat_test.matching(n);
   9.217 +  const MaxWeightedPerfectMatching<Graph>::MatchingMap& mmap =
   9.218 +    const_mat_test.matchingMap();
   9.219 +  e = mmap[n];
   9.220 +  const_mat_test.mate(n);
   9.221 +  
   9.222 +  int k = 0;
   9.223 +  const_mat_test.dualValue();
   9.224 +  const_mat_test.nodeValue(n);
   9.225 +  const_mat_test.blossomNum();
   9.226 +  const_mat_test.blossomSize(k);
   9.227 +  const_mat_test.blossomValue(k);
   9.228 +}
   9.229 +
   9.230 +void checkMatching(const SmartGraph& graph,
   9.231 +                   const MaxMatching<SmartGraph>& mm) {
   9.232 +  int num = 0;
   9.233 +
   9.234 +  IntNodeMap comp_index(graph);
   9.235 +  UnionFind<IntNodeMap> comp(comp_index);
   9.236 +
   9.237 +  int barrier_num = 0;
   9.238 +
   9.239 +  for (NodeIt n(graph); n != INVALID; ++n) {
   9.240 +    check(mm.status(n) == MaxMatching<SmartGraph>::EVEN ||
   9.241 +          mm.matching(n) != INVALID, "Wrong Gallai-Edmonds decomposition");
   9.242 +    if (mm.status(n) == MaxMatching<SmartGraph>::ODD) {
   9.243 +      ++barrier_num;
   9.244 +    } else {
   9.245 +      comp.insert(n);
   9.246 +    }
   9.247 +  }
   9.248 +
   9.249 +  for (EdgeIt e(graph); e != INVALID; ++e) {
   9.250 +    if (mm.matching(e)) {
   9.251 +      check(e == mm.matching(graph.u(e)), "Wrong matching");
   9.252 +      check(e == mm.matching(graph.v(e)), "Wrong matching");
   9.253 +      ++num;
   9.254 +    }
   9.255 +    check(mm.status(graph.u(e)) != MaxMatching<SmartGraph>::EVEN ||
   9.256 +          mm.status(graph.v(e)) != MaxMatching<SmartGraph>::MATCHED,
   9.257 +          "Wrong Gallai-Edmonds decomposition");
   9.258 +
   9.259 +    check(mm.status(graph.v(e)) != MaxMatching<SmartGraph>::EVEN ||
   9.260 +          mm.status(graph.u(e)) != MaxMatching<SmartGraph>::MATCHED,
   9.261 +          "Wrong Gallai-Edmonds decomposition");
   9.262 +
   9.263 +    if (mm.status(graph.u(e)) != MaxMatching<SmartGraph>::ODD &&
   9.264 +        mm.status(graph.v(e)) != MaxMatching<SmartGraph>::ODD) {
   9.265 +      comp.join(graph.u(e), graph.v(e));
   9.266 +    }
   9.267 +  }
   9.268 +
   9.269 +  std::set<int> comp_root;
   9.270 +  int odd_comp_num = 0;
   9.271 +  for (NodeIt n(graph); n != INVALID; ++n) {
   9.272 +    if (mm.status(n) != MaxMatching<SmartGraph>::ODD) {
   9.273 +      int root = comp.find(n);
   9.274 +      if (comp_root.find(root) == comp_root.end()) {
   9.275 +        comp_root.insert(root);
   9.276 +        if (comp.size(n) % 2 == 1) {
   9.277 +          ++odd_comp_num;
   9.278 +        }
   9.279 +      }
   9.280 +    }
   9.281 +  }
   9.282 +
   9.283 +  check(mm.matchingSize() == num, "Wrong matching");
   9.284 +  check(2 * num == countNodes(graph) - (odd_comp_num - barrier_num),
   9.285 +         "Wrong matching");
   9.286 +  return;
   9.287 +}
   9.288 +
   9.289 +void checkWeightedMatching(const SmartGraph& graph,
   9.290 +                   const SmartGraph::EdgeMap<int>& weight,
   9.291 +                   const MaxWeightedMatching<SmartGraph>& mwm) {
   9.292 +  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
   9.293 +    if (graph.u(e) == graph.v(e)) continue;
   9.294 +    int rw = mwm.nodeValue(graph.u(e)) + mwm.nodeValue(graph.v(e));
   9.295 +
   9.296 +    for (int i = 0; i < mwm.blossomNum(); ++i) {
   9.297 +      bool s = false, t = false;
   9.298 +      for (MaxWeightedMatching<SmartGraph>::BlossomIt n(mwm, i);
   9.299 +           n != INVALID; ++n) {
   9.300 +        if (graph.u(e) == n) s = true;
   9.301 +        if (graph.v(e) == n) t = true;
   9.302 +      }
   9.303 +      if (s == true && t == true) {
   9.304 +        rw += mwm.blossomValue(i);
   9.305 +      }
   9.306 +    }
   9.307 +    rw -= weight[e] * mwm.dualScale;
   9.308 +
   9.309 +    check(rw >= 0, "Negative reduced weight");
   9.310 +    check(rw == 0 || !mwm.matching(e),
   9.311 +          "Non-zero reduced weight on matching edge");
   9.312 +  }
   9.313 +
   9.314 +  int pv = 0;
   9.315 +  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
   9.316 +    if (mwm.matching(n) != INVALID) {
   9.317 +      check(mwm.nodeValue(n) >= 0, "Invalid node value");
   9.318 +      pv += weight[mwm.matching(n)];
   9.319 +      SmartGraph::Node o = graph.target(mwm.matching(n));
   9.320 +      check(mwm.mate(n) == o, "Invalid matching");
   9.321 +      check(mwm.matching(n) == graph.oppositeArc(mwm.matching(o)),
   9.322 +            "Invalid matching");
   9.323 +    } else {
   9.324 +      check(mwm.mate(n) == INVALID, "Invalid matching");
   9.325 +      check(mwm.nodeValue(n) == 0, "Invalid matching");
   9.326 +    }
   9.327 +  }
   9.328 +
   9.329 +  int dv = 0;
   9.330 +  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
   9.331 +    dv += mwm.nodeValue(n);
   9.332 +  }
   9.333 +
   9.334 +  for (int i = 0; i < mwm.blossomNum(); ++i) {
   9.335 +    check(mwm.blossomValue(i) >= 0, "Invalid blossom value");
   9.336 +    check(mwm.blossomSize(i) % 2 == 1, "Even blossom size");
   9.337 +    dv += mwm.blossomValue(i) * ((mwm.blossomSize(i) - 1) / 2);
   9.338 +  }
   9.339 +
   9.340 +  check(pv * mwm.dualScale == dv * 2, "Wrong duality");
   9.341 +
   9.342 +  return;
   9.343 +}
   9.344 +
   9.345 +void checkWeightedPerfectMatching(const SmartGraph& graph,
   9.346 +                          const SmartGraph::EdgeMap<int>& weight,
   9.347 +                          const MaxWeightedPerfectMatching<SmartGraph>& mwpm) {
   9.348 +  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
   9.349 +    if (graph.u(e) == graph.v(e)) continue;
   9.350 +    int rw = mwpm.nodeValue(graph.u(e)) + mwpm.nodeValue(graph.v(e));
   9.351 +
   9.352 +    for (int i = 0; i < mwpm.blossomNum(); ++i) {
   9.353 +      bool s = false, t = false;
   9.354 +      for (MaxWeightedPerfectMatching<SmartGraph>::BlossomIt n(mwpm, i);
   9.355 +           n != INVALID; ++n) {
   9.356 +        if (graph.u(e) == n) s = true;
   9.357 +        if (graph.v(e) == n) t = true;
   9.358 +      }
   9.359 +      if (s == true && t == true) {
   9.360 +        rw += mwpm.blossomValue(i);
   9.361 +      }
   9.362 +    }
   9.363 +    rw -= weight[e] * mwpm.dualScale;
   9.364 +
   9.365 +    check(rw >= 0, "Negative reduced weight");
   9.366 +    check(rw == 0 || !mwpm.matching(e),
   9.367 +          "Non-zero reduced weight on matching edge");
   9.368 +  }
   9.369 +
   9.370 +  int pv = 0;
   9.371 +  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
   9.372 +    check(mwpm.matching(n) != INVALID, "Non perfect");
   9.373 +    pv += weight[mwpm.matching(n)];
   9.374 +    SmartGraph::Node o = graph.target(mwpm.matching(n));
   9.375 +    check(mwpm.mate(n) == o, "Invalid matching");
   9.376 +    check(mwpm.matching(n) == graph.oppositeArc(mwpm.matching(o)),
   9.377 +          "Invalid matching");
   9.378 +  }
   9.379 +
   9.380 +  int dv = 0;
   9.381 +  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
   9.382 +    dv += mwpm.nodeValue(n);
   9.383 +  }
   9.384 +
   9.385 +  for (int i = 0; i < mwpm.blossomNum(); ++i) {
   9.386 +    check(mwpm.blossomValue(i) >= 0, "Invalid blossom value");
   9.387 +    check(mwpm.blossomSize(i) % 2 == 1, "Even blossom size");
   9.388 +    dv += mwpm.blossomValue(i) * ((mwpm.blossomSize(i) - 1) / 2);
   9.389 +  }
   9.390 +
   9.391 +  check(pv * mwpm.dualScale == dv * 2, "Wrong duality");
   9.392 +
   9.393 +  return;
   9.394 +}
   9.395 +
   9.396 +
   9.397 +int main() {
   9.398 +
   9.399 +  for (int i = 0; i < lgfn; ++i) {
   9.400 +    SmartGraph graph;
   9.401 +    SmartGraph::EdgeMap<int> weight(graph);
   9.402 +
   9.403 +    istringstream lgfs(lgf[i]);
   9.404 +    graphReader(graph, lgfs).
   9.405 +      edgeMap("weight", weight).run();
   9.406 +
   9.407 +    MaxMatching<SmartGraph> mm(graph);
   9.408 +    mm.run();
   9.409 +    checkMatching(graph, mm);
   9.410 +
   9.411 +    MaxWeightedMatching<SmartGraph> mwm(graph, weight);
   9.412 +    mwm.run();
   9.413 +    checkWeightedMatching(graph, weight, mwm);
   9.414 +
   9.415 +    MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
   9.416 +    bool perfect = mwpm.run();
   9.417 +
   9.418 +    check(perfect == (mm.matchingSize() * 2 == countNodes(graph)),
   9.419 +          "Perfect matching found");
   9.420 +
   9.421 +    if (perfect) {
   9.422 +      checkWeightedPerfectMatching(graph, weight, mwpm);
   9.423 +    }
   9.424 +  }
   9.425 +
   9.426 +  return 0;
   9.427 +}
    10.1 --- a/test/max_matching_test.cc	Tue Apr 21 10:34:49 2009 +0100
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,310 +0,0 @@
    10.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
    10.5 - *
    10.6 - * This file is a part of LEMON, a generic C++ optimization library.
    10.7 - *
    10.8 - * Copyright (C) 2003-2009
    10.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
   10.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
   10.11 - *
   10.12 - * Permission to use, modify and distribute this software is granted
   10.13 - * provided that this copyright notice appears in all copies. For
   10.14 - * precise terms see the accompanying LICENSE file.
   10.15 - *
   10.16 - * This software is provided "AS IS" with no warranty of any kind,
   10.17 - * express or implied, and with no claim as to its suitability for any
   10.18 - * purpose.
   10.19 - *
   10.20 - */
   10.21 -
   10.22 -#include <iostream>
   10.23 -#include <sstream>
   10.24 -#include <vector>
   10.25 -#include <queue>
   10.26 -#include <lemon/math.h>
   10.27 -#include <cstdlib>
   10.28 -
   10.29 -#include <lemon/max_matching.h>
   10.30 -#include <lemon/smart_graph.h>
   10.31 -#include <lemon/lgf_reader.h>
   10.32 -
   10.33 -#include "test_tools.h"
   10.34 -
   10.35 -using namespace std;
   10.36 -using namespace lemon;
   10.37 -
   10.38 -GRAPH_TYPEDEFS(SmartGraph);
   10.39 -
   10.40 -
   10.41 -const int lgfn = 3;
   10.42 -const std::string lgf[lgfn] = {
   10.43 -  "@nodes\n"
   10.44 -  "label\n"
   10.45 -  "0\n"
   10.46 -  "1\n"
   10.47 -  "2\n"
   10.48 -  "3\n"
   10.49 -  "4\n"
   10.50 -  "5\n"
   10.51 -  "6\n"
   10.52 -  "7\n"
   10.53 -  "@edges\n"
   10.54 -  "     label  weight\n"
   10.55 -  "7 4  0      984\n"
   10.56 -  "0 7  1      73\n"
   10.57 -  "7 1  2      204\n"
   10.58 -  "2 3  3      583\n"
   10.59 -  "2 7  4      565\n"
   10.60 -  "2 1  5      582\n"
   10.61 -  "0 4  6      551\n"
   10.62 -  "2 5  7      385\n"
   10.63 -  "1 5  8      561\n"
   10.64 -  "5 3  9      484\n"
   10.65 -  "7 5  10     904\n"
   10.66 -  "3 6  11     47\n"
   10.67 -  "7 6  12     888\n"
   10.68 -  "3 0  13     747\n"
   10.69 -  "6 1  14     310\n",
   10.70 -
   10.71 -  "@nodes\n"
   10.72 -  "label\n"
   10.73 -  "0\n"
   10.74 -  "1\n"
   10.75 -  "2\n"
   10.76 -  "3\n"
   10.77 -  "4\n"
   10.78 -  "5\n"
   10.79 -  "6\n"
   10.80 -  "7\n"
   10.81 -  "@edges\n"
   10.82 -  "     label  weight\n"
   10.83 -  "2 5  0      710\n"
   10.84 -  "0 5  1      241\n"
   10.85 -  "2 4  2      856\n"
   10.86 -  "2 6  3      762\n"
   10.87 -  "4 1  4      747\n"
   10.88 -  "6 1  5      962\n"
   10.89 -  "4 7  6      723\n"
   10.90 -  "1 7  7      661\n"
   10.91 -  "2 3  8      376\n"
   10.92 -  "1 0  9      416\n"
   10.93 -  "6 7  10     391\n",
   10.94 -
   10.95 -  "@nodes\n"
   10.96 -  "label\n"
   10.97 -  "0\n"
   10.98 -  "1\n"
   10.99 -  "2\n"
  10.100 -  "3\n"
  10.101 -  "4\n"
  10.102 -  "5\n"
  10.103 -  "6\n"
  10.104 -  "7\n"
  10.105 -  "@edges\n"
  10.106 -  "     label  weight\n"
  10.107 -  "6 2  0      553\n"
  10.108 -  "0 7  1      653\n"
  10.109 -  "6 3  2      22\n"
  10.110 -  "4 7  3      846\n"
  10.111 -  "7 2  4      981\n"
  10.112 -  "7 6  5      250\n"
  10.113 -  "5 2  6      539\n",
  10.114 -};
  10.115 -
  10.116 -void checkMatching(const SmartGraph& graph,
  10.117 -                   const MaxMatching<SmartGraph>& mm) {
  10.118 -  int num = 0;
  10.119 -
  10.120 -  IntNodeMap comp_index(graph);
  10.121 -  UnionFind<IntNodeMap> comp(comp_index);
  10.122 -
  10.123 -  int barrier_num = 0;
  10.124 -
  10.125 -  for (NodeIt n(graph); n != INVALID; ++n) {
  10.126 -    check(mm.decomposition(n) == MaxMatching<SmartGraph>::EVEN ||
  10.127 -          mm.matching(n) != INVALID, "Wrong Gallai-Edmonds decomposition");
  10.128 -    if (mm.decomposition(n) == MaxMatching<SmartGraph>::ODD) {
  10.129 -      ++barrier_num;
  10.130 -    } else {
  10.131 -      comp.insert(n);
  10.132 -    }
  10.133 -  }
  10.134 -
  10.135 -  for (EdgeIt e(graph); e != INVALID; ++e) {
  10.136 -    if (mm.matching(e)) {
  10.137 -      check(e == mm.matching(graph.u(e)), "Wrong matching");
  10.138 -      check(e == mm.matching(graph.v(e)), "Wrong matching");
  10.139 -      ++num;
  10.140 -    }
  10.141 -    check(mm.decomposition(graph.u(e)) != MaxMatching<SmartGraph>::EVEN ||
  10.142 -          mm.decomposition(graph.v(e)) != MaxMatching<SmartGraph>::MATCHED,
  10.143 -          "Wrong Gallai-Edmonds decomposition");
  10.144 -
  10.145 -    check(mm.decomposition(graph.v(e)) != MaxMatching<SmartGraph>::EVEN ||
  10.146 -          mm.decomposition(graph.u(e)) != MaxMatching<SmartGraph>::MATCHED,
  10.147 -          "Wrong Gallai-Edmonds decomposition");
  10.148 -
  10.149 -    if (mm.decomposition(graph.u(e)) != MaxMatching<SmartGraph>::ODD &&
  10.150 -        mm.decomposition(graph.v(e)) != MaxMatching<SmartGraph>::ODD) {
  10.151 -      comp.join(graph.u(e), graph.v(e));
  10.152 -    }
  10.153 -  }
  10.154 -
  10.155 -  std::set<int> comp_root;
  10.156 -  int odd_comp_num = 0;
  10.157 -  for (NodeIt n(graph); n != INVALID; ++n) {
  10.158 -    if (mm.decomposition(n) != MaxMatching<SmartGraph>::ODD) {
  10.159 -      int root = comp.find(n);
  10.160 -      if (comp_root.find(root) == comp_root.end()) {
  10.161 -        comp_root.insert(root);
  10.162 -        if (comp.size(n) % 2 == 1) {
  10.163 -          ++odd_comp_num;
  10.164 -        }
  10.165 -      }
  10.166 -    }
  10.167 -  }
  10.168 -
  10.169 -  check(mm.matchingSize() == num, "Wrong matching");
  10.170 -  check(2 * num == countNodes(graph) - (odd_comp_num - barrier_num),
  10.171 -         "Wrong matching");
  10.172 -  return;
  10.173 -}
  10.174 -
  10.175 -void checkWeightedMatching(const SmartGraph& graph,
  10.176 -                   const SmartGraph::EdgeMap<int>& weight,
  10.177 -                   const MaxWeightedMatching<SmartGraph>& mwm) {
  10.178 -  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
  10.179 -    if (graph.u(e) == graph.v(e)) continue;
  10.180 -    int rw = mwm.nodeValue(graph.u(e)) + mwm.nodeValue(graph.v(e));
  10.181 -
  10.182 -    for (int i = 0; i < mwm.blossomNum(); ++i) {
  10.183 -      bool s = false, t = false;
  10.184 -      for (MaxWeightedMatching<SmartGraph>::BlossomIt n(mwm, i);
  10.185 -           n != INVALID; ++n) {
  10.186 -        if (graph.u(e) == n) s = true;
  10.187 -        if (graph.v(e) == n) t = true;
  10.188 -      }
  10.189 -      if (s == true && t == true) {
  10.190 -        rw += mwm.blossomValue(i);
  10.191 -      }
  10.192 -    }
  10.193 -    rw -= weight[e] * mwm.dualScale;
  10.194 -
  10.195 -    check(rw >= 0, "Negative reduced weight");
  10.196 -    check(rw == 0 || !mwm.matching(e),
  10.197 -          "Non-zero reduced weight on matching edge");
  10.198 -  }
  10.199 -
  10.200 -  int pv = 0;
  10.201 -  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
  10.202 -    if (mwm.matching(n) != INVALID) {
  10.203 -      check(mwm.nodeValue(n) >= 0, "Invalid node value");
  10.204 -      pv += weight[mwm.matching(n)];
  10.205 -      SmartGraph::Node o = graph.target(mwm.matching(n));
  10.206 -      check(mwm.mate(n) == o, "Invalid matching");
  10.207 -      check(mwm.matching(n) == graph.oppositeArc(mwm.matching(o)),
  10.208 -            "Invalid matching");
  10.209 -    } else {
  10.210 -      check(mwm.mate(n) == INVALID, "Invalid matching");
  10.211 -      check(mwm.nodeValue(n) == 0, "Invalid matching");
  10.212 -    }
  10.213 -  }
  10.214 -
  10.215 -  int dv = 0;
  10.216 -  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
  10.217 -    dv += mwm.nodeValue(n);
  10.218 -  }
  10.219 -
  10.220 -  for (int i = 0; i < mwm.blossomNum(); ++i) {
  10.221 -    check(mwm.blossomValue(i) >= 0, "Invalid blossom value");
  10.222 -    check(mwm.blossomSize(i) % 2 == 1, "Even blossom size");
  10.223 -    dv += mwm.blossomValue(i) * ((mwm.blossomSize(i) - 1) / 2);
  10.224 -  }
  10.225 -
  10.226 -  check(pv * mwm.dualScale == dv * 2, "Wrong duality");
  10.227 -
  10.228 -  return;
  10.229 -}
  10.230 -
  10.231 -void checkWeightedPerfectMatching(const SmartGraph& graph,
  10.232 -                          const SmartGraph::EdgeMap<int>& weight,
  10.233 -                          const MaxWeightedPerfectMatching<SmartGraph>& mwpm) {
  10.234 -  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
  10.235 -    if (graph.u(e) == graph.v(e)) continue;
  10.236 -    int rw = mwpm.nodeValue(graph.u(e)) + mwpm.nodeValue(graph.v(e));
  10.237 -
  10.238 -    for (int i = 0; i < mwpm.blossomNum(); ++i) {
  10.239 -      bool s = false, t = false;
  10.240 -      for (MaxWeightedPerfectMatching<SmartGraph>::BlossomIt n(mwpm, i);
  10.241 -           n != INVALID; ++n) {
  10.242 -        if (graph.u(e) == n) s = true;
  10.243 -        if (graph.v(e) == n) t = true;
  10.244 -      }
  10.245 -      if (s == true && t == true) {
  10.246 -        rw += mwpm.blossomValue(i);
  10.247 -      }
  10.248 -    }
  10.249 -    rw -= weight[e] * mwpm.dualScale;
  10.250 -
  10.251 -    check(rw >= 0, "Negative reduced weight");
  10.252 -    check(rw == 0 || !mwpm.matching(e),
  10.253 -          "Non-zero reduced weight on matching edge");
  10.254 -  }
  10.255 -
  10.256 -  int pv = 0;
  10.257 -  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
  10.258 -    check(mwpm.matching(n) != INVALID, "Non perfect");
  10.259 -    pv += weight[mwpm.matching(n)];
  10.260 -    SmartGraph::Node o = graph.target(mwpm.matching(n));
  10.261 -    check(mwpm.mate(n) == o, "Invalid matching");
  10.262 -    check(mwpm.matching(n) == graph.oppositeArc(mwpm.matching(o)),
  10.263 -          "Invalid matching");
  10.264 -  }
  10.265 -
  10.266 -  int dv = 0;
  10.267 -  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
  10.268 -    dv += mwpm.nodeValue(n);
  10.269 -  }
  10.270 -
  10.271 -  for (int i = 0; i < mwpm.blossomNum(); ++i) {
  10.272 -    check(mwpm.blossomValue(i) >= 0, "Invalid blossom value");
  10.273 -    check(mwpm.blossomSize(i) % 2 == 1, "Even blossom size");
  10.274 -    dv += mwpm.blossomValue(i) * ((mwpm.blossomSize(i) - 1) / 2);
  10.275 -  }
  10.276 -
  10.277 -  check(pv * mwpm.dualScale == dv * 2, "Wrong duality");
  10.278 -
  10.279 -  return;
  10.280 -}
  10.281 -
  10.282 -
  10.283 -int main() {
  10.284 -
  10.285 -  for (int i = 0; i < lgfn; ++i) {
  10.286 -    SmartGraph graph;
  10.287 -    SmartGraph::EdgeMap<int> weight(graph);
  10.288 -
  10.289 -    istringstream lgfs(lgf[i]);
  10.290 -    graphReader(graph, lgfs).
  10.291 -      edgeMap("weight", weight).run();
  10.292 -
  10.293 -    MaxMatching<SmartGraph> mm(graph);
  10.294 -    mm.run();
  10.295 -    checkMatching(graph, mm);
  10.296 -
  10.297 -    MaxWeightedMatching<SmartGraph> mwm(graph, weight);
  10.298 -    mwm.run();
  10.299 -    checkWeightedMatching(graph, weight, mwm);
  10.300 -
  10.301 -    MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
  10.302 -    bool perfect = mwpm.run();
  10.303 -
  10.304 -    check(perfect == (mm.matchingSize() * 2 == countNodes(graph)),
  10.305 -          "Perfect matching found");
  10.306 -
  10.307 -    if (perfect) {
  10.308 -      checkWeightedPerfectMatching(graph, weight, mwpm);
  10.309 -    }
  10.310 -  }
  10.311 -
  10.312 -  return 0;
  10.313 -}
    11.1 --- a/tools/dimacs-solver.cc	Tue Apr 21 10:34:49 2009 +0100
    11.2 +++ b/tools/dimacs-solver.cc	Tue Apr 21 13:08:19 2009 +0100
    11.3 @@ -42,7 +42,7 @@
    11.4  
    11.5  #include <lemon/dijkstra.h>
    11.6  #include <lemon/preflow.h>
    11.7 -#include <lemon/max_matching.h>
    11.8 +#include <lemon/matching.h>
    11.9  
   11.10  using namespace lemon;
   11.11  typedef SmartDigraph Digraph;