| jacint@537 |      1 | // -*- C++ -*-
 | 
| alpar@921 |      2 | #ifndef LEMON_MAX_MATCHING_H
 | 
| alpar@921 |      3 | #define LEMON_MAX_MATCHING_H
 | 
| jacint@537 |      4 | 
 | 
| jacint@537 |      5 | ///\ingroup galgs
 | 
| jacint@537 |      6 | ///\file
 | 
| jacint@537 |      7 | ///\brief Maximum matching algorithm.
 | 
| jacint@537 |      8 | 
 | 
| jacint@537 |      9 | #include <queue>
 | 
| jacint@537 |     10 | 
 | 
| jacint@537 |     11 | #include <invalid.h>
 | 
| jacint@537 |     12 | #include <unionfind.h>
 | 
| jacint@537 |     13 | 
 | 
| alpar@921 |     14 | namespace lemon {
 | 
| jacint@537 |     15 | 
 | 
| jacint@537 |     16 |   /// \addtogroup galgs
 | 
| jacint@537 |     17 |   /// @{
 | 
| jacint@537 |     18 | 
 | 
| jacint@537 |     19 |   ///Maximum matching algorithms class.
 | 
| jacint@537 |     20 | 
 | 
| jacint@537 |     21 |   ///This class provides Edmonds' alternating forest matching
 | 
| jacint@537 |     22 |   ///algorithm. The starting matching (if any) can be passed to the
 | 
| jacint@537 |     23 |   ///algorithm using read-in functions \ref readNMapNode, \ref
 | 
| jacint@537 |     24 |   ///readNMapEdge or \ref readEMapBool depending on the container. The
 | 
| jacint@537 |     25 |   ///resulting maximum matching can be attained by write-out functions
 | 
| jacint@537 |     26 |   ///\ref writeNMapNode, \ref writeNMapEdge or \ref writeEMapBool
 | 
| jacint@537 |     27 |   ///depending on the preferred container. 
 | 
| alpar@682 |     28 |   ///
 | 
| jacint@537 |     29 |   ///The dual side of a mathcing is a map of the nodes to
 | 
| jacint@537 |     30 |   ///MaxMatching::pos_enum, having values D, A and C showing the
 | 
| jacint@537 |     31 |   ///Gallai-Edmonds decomposition of the graph. The nodes in D induce
 | 
| jacint@537 |     32 |   ///a graph with factor-critical components, the nodes in A form the
 | 
| jacint@537 |     33 |   ///barrier, and the nodes in C induce a graph having a perfect
 | 
| jacint@537 |     34 |   ///matching. This decomposition can be attained by calling \ref
 | 
| jacint@537 |     35 |   ///writePos after running the algorithm. Before subsequent runs,
 | 
| jacint@537 |     36 |   ///the function \ref resetPos() must be called.
 | 
| alpar@682 |     37 |   ///
 | 
| jacint@537 |     38 |   ///\param Graph The undirected graph type the algorithm runs on.
 | 
| alpar@682 |     39 |   ///
 | 
| jacint@537 |     40 |   ///\author Jacint Szabo  
 | 
| jacint@537 |     41 |   template <typename Graph>
 | 
| jacint@537 |     42 |   class MaxMatching {
 | 
| jacint@537 |     43 |     typedef typename Graph::Node Node;
 | 
| jacint@537 |     44 |     typedef typename Graph::Edge Edge;
 | 
| jacint@537 |     45 |     typedef typename Graph::EdgeIt EdgeIt;
 | 
| jacint@537 |     46 |     typedef typename Graph::NodeIt NodeIt;
 | 
| jacint@537 |     47 |     typedef typename Graph::OutEdgeIt OutEdgeIt;
 | 
| jacint@537 |     48 | 
 | 
| jacint@537 |     49 |     typedef UnionFindEnum<Node, Graph::template NodeMap> UFE;
 | 
| jacint@537 |     50 | 
 | 
| jacint@537 |     51 |   public:
 | 
| jacint@537 |     52 |     
 | 
| jacint@537 |     53 |     ///Indicates the Gallai-Edmonds decomposition of the graph.
 | 
| jacint@537 |     54 | 
 | 
| jacint@537 |     55 |     ///Indicates the Gallai-Edmonds decomposition of the graph, which
 | 
| jacint@537 |     56 |     ///shows an upper bound on the size of a maximum matching. The
 | 
| alpar@586 |     57 |     ///nodes with pos_enum \c D induce a graph with factor-critical
 | 
| alpar@586 |     58 |     ///components, the nodes in \c A form the canonical barrier, and the
 | 
| alpar@586 |     59 |     ///nodes in \c C induce a graph having a perfect matching. 
 | 
| jacint@537 |     60 |     enum pos_enum {
 | 
| jacint@537 |     61 |       D=0,
 | 
| jacint@537 |     62 |       A=1,
 | 
| jacint@537 |     63 |       C=2
 | 
| jacint@537 |     64 |     }; 
 | 
| jacint@537 |     65 | 
 | 
| jacint@537 |     66 |   private:
 | 
| jacint@537 |     67 | 
 | 
| jacint@537 |     68 |     const Graph& G;
 | 
| jacint@537 |     69 |     typename Graph::template NodeMap<Node> mate;
 | 
| jacint@537 |     70 |     typename Graph::template NodeMap<pos_enum> position;
 | 
| jacint@537 |     71 |      
 | 
| jacint@537 |     72 |   public:
 | 
| jacint@537 |     73 |     
 | 
| jacint@582 |     74 |     MaxMatching(const Graph& _G) : G(_G), mate(_G,INVALID), position(_G,C) {}
 | 
| jacint@537 |     75 | 
 | 
| jacint@537 |     76 |     ///Runs Edmonds' algorithm.
 | 
| jacint@537 |     77 | 
 | 
| jacint@537 |     78 |     ///Runs Edmonds' algorithm for sparse graphs (edgeNum >=
 | 
| jacint@537 |     79 |     ///2*nodeNum), and a heuristical Edmonds' algorithm with a
 | 
| jacint@537 |     80 |     ///heuristic of postponing shrinks for dense graphs. \pre Before
 | 
| jacint@537 |     81 |     ///the subsequent calls \ref resetPos must be called.
 | 
| jacint@582 |     82 |     inline void run();
 | 
| jacint@537 |     83 | 
 | 
| jacint@537 |     84 |     ///Runs Edmonds' algorithm.
 | 
| jacint@537 |     85 |     
 | 
| jacint@537 |     86 |     ///If heur=0 it runs Edmonds' algorithm. If heur=1 it runs
 | 
| jacint@537 |     87 |     ///Edmonds' algorithm with a heuristic of postponing shrinks,
 | 
| jacint@537 |     88 |     ///giving a faster algorithm for dense graphs.  \pre Before the
 | 
| jacint@537 |     89 |     ///subsequent calls \ref resetPos must be called.
 | 
| jacint@537 |     90 |     void runEdmonds( int heur );
 | 
| jacint@537 |     91 | 
 | 
| jacint@537 |     92 |     ///Finds a greedy matching starting from the actual matching.
 | 
| jacint@537 |     93 |     
 | 
| jacint@537 |     94 |     ///Starting form the actual matching stored, it finds a maximal
 | 
| jacint@537 |     95 |     ///greedy matching.
 | 
| jacint@537 |     96 |     void greedyMatching();
 | 
| jacint@537 |     97 | 
 | 
| jacint@537 |     98 |     ///Returns the size of the actual matching stored.
 | 
| jacint@537 |     99 | 
 | 
| jacint@537 |    100 |     ///Returns the size of the actual matching stored. After \ref
 | 
| jacint@537 |    101 |     ///run() it returns the size of a maximum matching in the graph.
 | 
| jacint@582 |    102 |     int size () const;
 | 
| jacint@537 |    103 | 
 | 
| jacint@537 |    104 |     ///Resets the map storing the Gallai-Edmonds decomposition.
 | 
| jacint@537 |    105 |     
 | 
| jacint@537 |    106 |     ///Resets the map storing the Gallai-Edmonds decomposition of the
 | 
| jacint@537 |    107 |     ///graph, making it possible to run the algorithm. Must be called
 | 
| jacint@537 |    108 |     ///before all runs of the Edmonds algorithm, except for the first
 | 
| jacint@537 |    109 |     ///run.
 | 
| jacint@537 |    110 |     void resetPos();
 | 
| jacint@537 |    111 | 
 | 
| jacint@537 |    112 |     ///Resets the actual matching to the empty matching.
 | 
| jacint@537 |    113 | 
 | 
| jacint@537 |    114 |     ///Resets the actual matching to the empty matching.  
 | 
| jacint@537 |    115 |     ///
 | 
| jacint@537 |    116 |     void resetMatching();
 | 
| jacint@537 |    117 | 
 | 
| jacint@537 |    118 |     ///Reads a matching from a \c Node map of \c Nodes.
 | 
| jacint@537 |    119 | 
 | 
| jacint@537 |    120 |     ///Reads a matching from a \c Node map of \c Nodes. This map must be \e
 | 
| jacint@537 |    121 |     ///symmetric, i.e. if \c map[u]=v then \c map[v]=u must hold, and
 | 
| jacint@537 |    122 |     ///now \c uv is an edge of the matching.
 | 
| jacint@537 |    123 |     template<typename NMapN>
 | 
| jacint@537 |    124 |     void readNMapNode(NMapN& map) {
 | 
| jacint@537 |    125 |       NodeIt v;
 | 
| jacint@537 |    126 |       for( G.first(v); G.valid(v); G.next(v)) {
 | 
| jacint@537 |    127 | 	mate.set(v,map[v]);   
 | 
| jacint@537 |    128 |       } 
 | 
| jacint@537 |    129 |     } 
 | 
| jacint@537 |    130 |     
 | 
| jacint@537 |    131 |     ///Writes the stored matching to a \c Node map of \c Nodes.
 | 
| jacint@537 |    132 | 
 | 
| jacint@537 |    133 |     ///Writes the stored matching to a \c Node map of \c Nodes. The
 | 
| jacint@537 |    134 |     ///resulting map will be \e symmetric, i.e. if \c map[u]=v then \c
 | 
| jacint@537 |    135 |     ///map[v]=u will hold, and now \c uv is an edge of the matching.
 | 
| jacint@537 |    136 |     template<typename NMapN>
 | 
| jacint@582 |    137 |     void writeNMapNode (NMapN& map) const {
 | 
| jacint@537 |    138 |       NodeIt v;
 | 
| jacint@537 |    139 |       for( G.first(v); G.valid(v); G.next(v)) {
 | 
| jacint@537 |    140 | 	map.set(v,mate[v]);   
 | 
| jacint@537 |    141 |       } 
 | 
| jacint@537 |    142 |     } 
 | 
| jacint@537 |    143 | 
 | 
| jacint@537 |    144 |     ///Reads a matching from a \c Node map of \c Edges.
 | 
| jacint@537 |    145 | 
 | 
| jacint@537 |    146 |     ///Reads a matching from a \c Node map of incident \c Edges. This
 | 
| jacint@537 |    147 |     ///map must have the property that if \c G.bNode(map[u])=v then \c
 | 
| jacint@537 |    148 |     ///G.bNode(map[v])=u must hold, and now this edge is an edge of
 | 
| jacint@537 |    149 |     ///the matching.
 | 
| jacint@537 |    150 |     template<typename NMapE>
 | 
| jacint@537 |    151 |     void readNMapEdge(NMapE& map) {
 | 
| jacint@537 |    152 |       NodeIt v;
 | 
| jacint@537 |    153 |       for( G.first(v); G.valid(v); G.next(v)) {
 | 
| jacint@537 |    154 | 	Edge e=map[v];
 | 
| jacint@537 |    155 | 	if ( G.valid(e) )
 | 
| jacint@537 |    156 | 	  G.tail(e) == v ? mate.set(v,G.head(e)) : mate.set(v,G.tail(e)); 
 | 
| jacint@537 |    157 |       } 
 | 
| jacint@537 |    158 |     } 
 | 
| jacint@537 |    159 |     
 | 
| jacint@537 |    160 |     ///Writes the matching stored to a \c Node map of \c Edges.
 | 
| jacint@537 |    161 | 
 | 
| jacint@537 |    162 |     ///Writes the stored matching to a \c Node map of incident \c
 | 
| jacint@537 |    163 |     ///Edges. This map will have the property that if \c
 | 
| jacint@537 |    164 |     ///G.bNode(map[u])=v then \c G.bNode(map[v])=u holds, and now this
 | 
| jacint@537 |    165 |     ///edge is an edge of the matching.
 | 
| jacint@537 |    166 |     template<typename NMapE>
 | 
| jacint@582 |    167 |     void writeNMapEdge (NMapE& map)  const {
 | 
| jacint@537 |    168 |       typename Graph::template NodeMap<bool> todo(G,false); 
 | 
| jacint@537 |    169 |       NodeIt v;
 | 
| jacint@537 |    170 |       for( G.first(v); G.valid(v); G.next(v)) {
 | 
| jacint@537 |    171 | 	if ( mate[v]!=INVALID ) todo.set(v,true); 
 | 
| jacint@537 |    172 |       }
 | 
| jacint@537 |    173 |       NodeIt e;
 | 
| jacint@537 |    174 |       for( G.first(e); G.valid(e); G.next(e)) {
 | 
| jacint@537 |    175 | 	if ( todo[G.head(e)] && todo[G.tail(e)] ) {
 | 
| jacint@537 |    176 | 	  Node u=G.tail(e);
 | 
| jacint@537 |    177 | 	  Node v=G.head(e); 
 | 
| jacint@537 |    178 | 	  if ( mate[u]=v && mate[v]=u ) {
 | 
| jacint@537 |    179 | 	    map.set(u,e);
 | 
| jacint@537 |    180 | 	    map.set(v,e);
 | 
| jacint@537 |    181 | 	    todo.set(u,false);
 | 
| jacint@537 |    182 | 	    todo.set(v,false);
 | 
| jacint@537 |    183 | 	  }
 | 
| jacint@537 |    184 | 	}
 | 
| jacint@537 |    185 |       }
 | 
| jacint@537 |    186 |     } 
 | 
| jacint@537 |    187 | 
 | 
| jacint@537 |    188 |     ///Reads a matching from an \c Edge map of \c bools.
 | 
| jacint@537 |    189 |     
 | 
| jacint@537 |    190 |     ///Reads a matching from an \c Edge map of \c bools. This map must
 | 
| jacint@537 |    191 |     ///have the property that there are no two adjacent edges \c e, \c
 | 
| jacint@537 |    192 |     ///f with \c map[e]=map[f]=true. The edges \c e with \c
 | 
| jacint@537 |    193 |     ///map[e]=true form the matching.
 | 
| jacint@537 |    194 |     template<typename EMapB>
 | 
| jacint@537 |    195 |     void readEMapBool(EMapB& map) {
 | 
| jacint@537 |    196 |       EdgeIt e;
 | 
| jacint@537 |    197 |       for( G.first(e); G.valid(e); G.next(e)) {
 | 
| jacint@537 |    198 | 	if ( G.valid(e) ) {
 | 
| jacint@537 |    199 | 	  Node u=G.tail(e);	  
 | 
| jacint@537 |    200 | 	  Node v=G.head(e);
 | 
| jacint@537 |    201 | 	  mate.set(u,v);
 | 
| jacint@537 |    202 | 	  mate.set(v,u);
 | 
| jacint@537 |    203 | 	} 
 | 
| jacint@537 |    204 |       } 
 | 
| jacint@537 |    205 |     }
 | 
| jacint@537 |    206 | 
 | 
| jacint@537 |    207 | 
 | 
| jacint@537 |    208 |     ///Writes the matching stored to an \c Edge map of \c bools.
 | 
| jacint@537 |    209 | 
 | 
| jacint@537 |    210 |     ///Writes the matching stored to an \c Edge map of \c bools. This
 | 
| jacint@537 |    211 |     ///map will have the property that there are no two adjacent edges
 | 
| jacint@537 |    212 |     ///\c e, \c f with \c map[e]=map[f]=true. The edges \c e with \c
 | 
| jacint@537 |    213 |     ///map[e]=true form the matching.
 | 
| jacint@537 |    214 |     template<typename EMapB>
 | 
| jacint@582 |    215 |     void writeEMapBool (EMapB& map) const {
 | 
| jacint@537 |    216 |       typename Graph::template NodeMap<bool> todo(G,false); 
 | 
| jacint@537 |    217 |       NodeIt v;
 | 
| jacint@537 |    218 |       for( G.first(v); G.valid(v); G.next(v)) {
 | 
| jacint@537 |    219 | 	if ( mate[v]!=INVALID ) todo.set(v,true); 
 | 
| jacint@537 |    220 |       }
 | 
| jacint@537 |    221 |       
 | 
| jacint@537 |    222 |       NodeIt e;
 | 
| jacint@537 |    223 |       for( G.first(e); G.valid(e); G.next(e)) {
 | 
| jacint@537 |    224 | 	map.set(e,false);
 | 
| jacint@537 |    225 | 	if ( todo[G.head(e)] && todo[G.tail(e)] ) {
 | 
| jacint@537 |    226 | 	  Node u=G.tail(e);
 | 
| jacint@537 |    227 | 	  Node v=G.head(e); 
 | 
| jacint@537 |    228 | 	  if ( mate[u]=v && mate[v]=u ) {
 | 
| jacint@537 |    229 | 	    map.set(e,true);
 | 
| jacint@537 |    230 | 	    todo.set(u,false);
 | 
| jacint@537 |    231 | 	    todo.set(v,false);
 | 
| jacint@537 |    232 | 	  }
 | 
| jacint@537 |    233 | 	}
 | 
| jacint@537 |    234 |       }
 | 
| jacint@537 |    235 |     }
 | 
| jacint@537 |    236 | 
 | 
| jacint@537 |    237 |     ///Writes the canonical decomposition of the graph after running
 | 
| jacint@537 |    238 |     ///the algorithm.
 | 
| jacint@537 |    239 | 
 | 
| jacint@537 |    240 |     ///After calling any run methods of the class, and before calling
 | 
| jacint@537 |    241 |     ///\ref resetPos(), it writes the Gallai-Edmonds canonical
 | 
| alpar@682 |    242 |     ///decomposition of the graph. \c map must be a node map
 | 
| alpar@682 |    243 |     ///of \ref pos_enum 's.
 | 
| jacint@537 |    244 |     template<typename NMapEnum>
 | 
| jacint@582 |    245 |     void writePos (NMapEnum& map) const {
 | 
| jacint@537 |    246 |       NodeIt v;
 | 
| jacint@537 |    247 |       for( G.first(v); G.valid(v); G.next(v)) map.set(v,position[v]);
 | 
| jacint@537 |    248 |     }
 | 
| jacint@537 |    249 | 
 | 
| jacint@537 |    250 |   private: 
 | 
| jacint@537 |    251 | 
 | 
| jacint@537 |    252 |     void lateShrink(Node v, typename Graph::template NodeMap<Node>& ear,  
 | 
| jacint@537 |    253 | 		    UFE& blossom, UFE& tree);
 | 
| jacint@537 |    254 | 
 | 
| jacint@537 |    255 |     void normShrink(Node v, typename Graph::NodeMap<Node>& ear,  
 | 
| jacint@537 |    256 | 		    UFE& blossom, UFE& tree);
 | 
| jacint@537 |    257 | 
 | 
| jacint@537 |    258 |     bool noShrinkStep(Node x, typename Graph::NodeMap<Node>& ear,  
 | 
| jacint@537 |    259 | 		      UFE& blossom, UFE& tree, std::queue<Node>& Q);
 | 
| jacint@537 |    260 | 
 | 
| jacint@537 |    261 |     void shrinkStep(Node& top, Node& middle, Node& bottom, typename Graph::NodeMap<Node>& ear,  
 | 
| jacint@537 |    262 | 		    UFE& blossom, UFE& tree, std::queue<Node>& Q);
 | 
| jacint@537 |    263 | 
 | 
| jacint@537 |    264 |     void augment(Node x, typename Graph::NodeMap<Node>& ear,  
 | 
| jacint@537 |    265 | 		 UFE& blossom, UFE& tree);
 | 
| jacint@537 |    266 | 
 | 
| jacint@537 |    267 |   };
 | 
| jacint@537 |    268 | 
 | 
| jacint@537 |    269 | 
 | 
| jacint@537 |    270 |   // **********************************************************************
 | 
| jacint@537 |    271 |   //  IMPLEMENTATIONS
 | 
| jacint@537 |    272 |   // **********************************************************************
 | 
| jacint@537 |    273 | 
 | 
| jacint@537 |    274 | 
 | 
| jacint@537 |    275 |   template <typename Graph>
 | 
| jacint@537 |    276 |   void MaxMatching<Graph>::run() {
 | 
| jacint@537 |    277 |     if ( G.edgeNum() > 2*G.nodeNum() ) {
 | 
| jacint@537 |    278 |       greedyMatching();
 | 
| jacint@537 |    279 |       runEdmonds(1);
 | 
| jacint@537 |    280 |     } else runEdmonds(0);
 | 
| jacint@537 |    281 |   }
 | 
| jacint@537 |    282 | 
 | 
| jacint@537 |    283 |   template <typename Graph>
 | 
| jacint@537 |    284 |   void MaxMatching<Graph>::runEdmonds( int heur=1 ) {
 | 
| jacint@537 |    285 |       
 | 
| jacint@537 |    286 |     typename Graph::template NodeMap<Node> ear(G,INVALID); 
 | 
| jacint@537 |    287 |     //undefined for the base nodes of the blossoms (i.e. for the
 | 
| jacint@537 |    288 |     //representative elements of UFE blossom) and for the nodes in C
 | 
| jacint@537 |    289 |       
 | 
| jacint@537 |    290 |     typename UFE::MapType blossom_base(G);
 | 
| jacint@537 |    291 |     UFE blossom(blossom_base);
 | 
| jacint@537 |    292 |     typename UFE::MapType tree_base(G);
 | 
| jacint@537 |    293 |     UFE tree(tree_base);
 | 
| jacint@537 |    294 | 	
 | 
| jacint@537 |    295 |     NodeIt v;
 | 
| jacint@537 |    296 |     for( G.first(v); G.valid(v); G.next(v) ) {
 | 
| jacint@537 |    297 |       if ( position[v]==C && mate[v]==INVALID ) {
 | 
| jacint@537 |    298 | 	blossom.insert(v);
 | 
| jacint@537 |    299 | 	tree.insert(v); 
 | 
| jacint@537 |    300 | 	position.set(v,D);
 | 
| jacint@537 |    301 | 	if ( heur == 1 ) lateShrink( v, ear, blossom, tree );
 | 
| jacint@537 |    302 | 	else normShrink( v, ear, blossom, tree );
 | 
| jacint@537 |    303 |       }
 | 
| jacint@537 |    304 |     }
 | 
| jacint@537 |    305 |   }
 | 
| jacint@537 |    306 |     
 | 
| jacint@537 |    307 |   template <typename Graph>
 | 
| jacint@537 |    308 |   void MaxMatching<Graph>::lateShrink(Node v, typename Graph::template NodeMap<Node>& ear,  
 | 
| jacint@537 |    309 | 				      UFE& blossom, UFE& tree) {
 | 
| jacint@537 |    310 |      
 | 
| jacint@537 |    311 |     std::queue<Node> Q;   //queue of the totally unscanned nodes
 | 
| jacint@537 |    312 |     Q.push(v);  
 | 
| jacint@537 |    313 |     std::queue<Node> R;   
 | 
| jacint@537 |    314 |     //queue of the nodes which must be scanned for a possible shrink
 | 
| jacint@537 |    315 |       
 | 
| jacint@537 |    316 |     while ( !Q.empty() ) {
 | 
| jacint@537 |    317 |       Node x=Q.front();
 | 
| jacint@537 |    318 |       Q.pop();
 | 
| jacint@537 |    319 |       if ( noShrinkStep( x, ear, blossom, tree, Q ) ) return;
 | 
| jacint@537 |    320 |       else R.push(x);
 | 
| jacint@537 |    321 |     }
 | 
| jacint@537 |    322 |       
 | 
| jacint@537 |    323 |     while ( !R.empty() ) {
 | 
| jacint@537 |    324 |       Node x=R.front();
 | 
| jacint@537 |    325 |       R.pop();
 | 
| jacint@537 |    326 | 	
 | 
| jacint@537 |    327 |       OutEdgeIt e;
 | 
| jacint@537 |    328 |       for( G.first(e,x); G.valid(e); G.next(e) ) {
 | 
| jacint@537 |    329 | 	Node y=G.bNode(e);
 | 
| jacint@537 |    330 | 
 | 
| jacint@537 |    331 | 	if ( position[y] == D && blossom.find(x) != blossom.find(y) ) { 
 | 
| jacint@537 |    332 | 	  //x and y must be in the same tree
 | 
| jacint@537 |    333 | 	
 | 
| jacint@537 |    334 | 	  typename Graph::template NodeMap<bool> path(G,false);
 | 
| jacint@537 |    335 | 
 | 
| jacint@537 |    336 | 	  Node b=blossom.find(x);
 | 
| jacint@537 |    337 | 	  path.set(b,true);
 | 
| jacint@537 |    338 | 	  b=mate[b];
 | 
| jacint@537 |    339 | 	  while ( b!=INVALID ) { 
 | 
| jacint@537 |    340 | 	    b=blossom.find(ear[b]);
 | 
| jacint@537 |    341 | 	    path.set(b,true);
 | 
| jacint@537 |    342 | 	    b=mate[b];
 | 
| jacint@537 |    343 | 	  } //going till the root
 | 
| jacint@537 |    344 | 	
 | 
| jacint@537 |    345 | 	  Node top=y;
 | 
| jacint@537 |    346 | 	  Node middle=blossom.find(top);
 | 
| jacint@537 |    347 | 	  Node bottom=x;
 | 
| jacint@537 |    348 | 	  while ( !path[middle] )
 | 
| jacint@537 |    349 | 	    shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
 | 
| jacint@537 |    350 | 		  
 | 
| jacint@537 |    351 | 	  Node base=middle;
 | 
| jacint@537 |    352 | 	  top=x;
 | 
| jacint@537 |    353 | 	  middle=blossom.find(top);
 | 
| jacint@537 |    354 | 	  bottom=y;
 | 
| jacint@537 |    355 | 	  Node blossom_base=blossom.find(base);
 | 
| jacint@537 |    356 | 	  while ( middle!=blossom_base )
 | 
| jacint@537 |    357 | 	    shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
 | 
| jacint@537 |    358 | 		  
 | 
| jacint@537 |    359 | 	  blossom.makeRep(base);
 | 
| jacint@537 |    360 | 	} // if shrink is needed
 | 
| jacint@537 |    361 | 
 | 
| jacint@537 |    362 | 	while ( !Q.empty() ) {
 | 
| jacint@537 |    363 | 	  Node x=Q.front();
 | 
| jacint@537 |    364 | 	  Q.pop();
 | 
| jacint@537 |    365 | 	  if ( noShrinkStep(x, ear, blossom, tree, Q) ) return;
 | 
| jacint@537 |    366 | 	  else R.push(x);
 | 
| jacint@537 |    367 | 	}
 | 
| jacint@537 |    368 |       } //for e
 | 
| jacint@537 |    369 |     } // while ( !R.empty() )
 | 
| jacint@537 |    370 |   }
 | 
| jacint@537 |    371 | 
 | 
| jacint@537 |    372 |   template <typename Graph>
 | 
| jacint@537 |    373 |   void MaxMatching<Graph>::normShrink(Node v, typename Graph::NodeMap<Node>& ear,  
 | 
| jacint@537 |    374 | 				      UFE& blossom, UFE& tree) {
 | 
| jacint@537 |    375 | 
 | 
| jacint@537 |    376 |     std::queue<Node> Q;   //queue of the unscanned nodes
 | 
| jacint@537 |    377 |     Q.push(v);  
 | 
| jacint@537 |    378 |     while ( !Q.empty() ) {
 | 
| jacint@537 |    379 |       Node x=Q.front();
 | 
| jacint@537 |    380 |       Q.pop();
 | 
| jacint@537 |    381 | 	
 | 
| jacint@537 |    382 |       OutEdgeIt e;
 | 
| jacint@537 |    383 |       for( G.first(e,x); G.valid(e); G.next(e) ) {
 | 
| jacint@537 |    384 | 	Node y=G.bNode(e);
 | 
| jacint@537 |    385 | 	      
 | 
| jacint@537 |    386 | 	switch ( position[y] ) {
 | 
| jacint@537 |    387 | 	case D:          //x and y must be in the same tree
 | 
| jacint@537 |    388 | 	  if ( blossom.find(x) != blossom.find(y) ) { //shrink
 | 
| jacint@537 |    389 | 	    typename Graph::template NodeMap<bool> path(G,false);
 | 
| jacint@537 |    390 | 	      
 | 
| jacint@537 |    391 | 	    Node b=blossom.find(x);
 | 
| jacint@537 |    392 | 	    path.set(b,true);
 | 
| jacint@537 |    393 | 	    b=mate[b];
 | 
| jacint@537 |    394 | 	    while ( b!=INVALID ) { 
 | 
| jacint@537 |    395 | 	      b=blossom.find(ear[b]);
 | 
| jacint@537 |    396 | 	      path.set(b,true);
 | 
| jacint@537 |    397 | 	      b=mate[b];
 | 
| jacint@537 |    398 | 	    } //going till the root
 | 
| jacint@537 |    399 | 	
 | 
| jacint@537 |    400 | 	    Node top=y;
 | 
| jacint@537 |    401 | 	    Node middle=blossom.find(top);
 | 
| jacint@537 |    402 | 	    Node bottom=x;
 | 
| jacint@537 |    403 | 	    while ( !path[middle] )
 | 
| jacint@537 |    404 | 	      shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
 | 
| jacint@537 |    405 | 		
 | 
| jacint@537 |    406 | 	    Node base=middle;
 | 
| jacint@537 |    407 | 	    top=x;
 | 
| jacint@537 |    408 | 	    middle=blossom.find(top);
 | 
| jacint@537 |    409 | 	    bottom=y;
 | 
| jacint@537 |    410 | 	    Node blossom_base=blossom.find(base);
 | 
| jacint@537 |    411 | 	    while ( middle!=blossom_base )
 | 
| jacint@537 |    412 | 	      shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
 | 
| jacint@537 |    413 | 		
 | 
| jacint@537 |    414 | 	    blossom.makeRep(base);
 | 
| jacint@537 |    415 | 	  }
 | 
| jacint@537 |    416 | 	  break;
 | 
| jacint@537 |    417 | 	case C:
 | 
| jacint@537 |    418 | 	  if ( mate[y]!=INVALID ) {   //grow
 | 
| jacint@537 |    419 | 	    ear.set(y,x);
 | 
| jacint@537 |    420 | 	    Node w=mate[y];
 | 
| jacint@537 |    421 | 	    blossom.insert(w);
 | 
| jacint@537 |    422 | 	    position.set(y,A); 
 | 
| jacint@537 |    423 | 	    position.set(w,D); 
 | 
| jacint@537 |    424 | 	    tree.insert(y);
 | 
| jacint@537 |    425 | 	    tree.insert(w);
 | 
| jacint@537 |    426 | 	    tree.join(y,blossom.find(x));  
 | 
| jacint@537 |    427 | 	    tree.join(w,y);  
 | 
| jacint@537 |    428 | 	    Q.push(w);
 | 
| jacint@537 |    429 | 	  } else {                 //augment  
 | 
| jacint@537 |    430 | 	    augment(x, ear, blossom, tree);
 | 
| jacint@537 |    431 | 	    mate.set(x,y);
 | 
| jacint@537 |    432 | 	    mate.set(y,x);
 | 
| jacint@537 |    433 | 	    return;
 | 
| jacint@537 |    434 | 	  } //if 
 | 
| jacint@537 |    435 | 	  break;
 | 
| jacint@537 |    436 | 	default: break;
 | 
| jacint@537 |    437 | 	}
 | 
| jacint@537 |    438 |       }
 | 
| jacint@537 |    439 |     }
 | 
| jacint@537 |    440 |   }
 | 
| jacint@537 |    441 | 
 | 
| jacint@537 |    442 |   template <typename Graph>
 | 
| jacint@537 |    443 |   void MaxMatching<Graph>::greedyMatching() {
 | 
| jacint@537 |    444 |     NodeIt v;
 | 
| jacint@537 |    445 |     for( G.first(v); G.valid(v); G.next(v) )
 | 
| jacint@537 |    446 |       if ( mate[v]==INVALID ) {
 | 
| jacint@537 |    447 | 	OutEdgeIt e;
 | 
| jacint@537 |    448 | 	for( G.first(e,v); G.valid(e); G.next(e) ) {
 | 
| jacint@537 |    449 | 	  Node y=G.bNode(e);
 | 
| jacint@537 |    450 | 	  if ( mate[y]==INVALID && y!=v ) {
 | 
| jacint@537 |    451 | 	    mate.set(v,y);
 | 
| jacint@537 |    452 | 	    mate.set(y,v);
 | 
| jacint@537 |    453 | 	    break;
 | 
| jacint@537 |    454 | 	  }
 | 
| jacint@537 |    455 | 	}
 | 
| jacint@537 |    456 |       } 
 | 
| jacint@537 |    457 |   }
 | 
| jacint@537 |    458 |    
 | 
| jacint@537 |    459 |   template <typename Graph>
 | 
| jacint@582 |    460 |   int MaxMatching<Graph>::size() const {
 | 
| jacint@537 |    461 |     int s=0;
 | 
| jacint@537 |    462 |     NodeIt v;
 | 
| jacint@537 |    463 |     for(G.first(v); G.valid(v); G.next(v) ) {
 | 
| jacint@537 |    464 |       if ( G.valid(mate[v]) ) {
 | 
| jacint@537 |    465 | 	++s;
 | 
| jacint@537 |    466 |       }
 | 
| jacint@537 |    467 |     }
 | 
| jacint@537 |    468 |     return (int)s/2;
 | 
| jacint@537 |    469 |   }
 | 
| jacint@537 |    470 | 
 | 
| jacint@537 |    471 |   template <typename Graph>
 | 
| jacint@537 |    472 |   void MaxMatching<Graph>::resetPos() {
 | 
| jacint@537 |    473 |     NodeIt v;
 | 
| jacint@537 |    474 |     for( G.first(v); G.valid(v); G.next(v))
 | 
| jacint@537 |    475 |       position.set(v,C);      
 | 
| jacint@537 |    476 |   }
 | 
| jacint@537 |    477 | 
 | 
| jacint@537 |    478 |   template <typename Graph>
 | 
| jacint@537 |    479 |   void MaxMatching<Graph>::resetMatching() {
 | 
| jacint@537 |    480 |     NodeIt v;
 | 
| jacint@537 |    481 |     for( G.first(v); G.valid(v); G.next(v))
 | 
| jacint@537 |    482 |       mate.set(v,INVALID);      
 | 
| jacint@537 |    483 |   }
 | 
| jacint@537 |    484 | 
 | 
| jacint@537 |    485 |   template <typename Graph>
 | 
| jacint@537 |    486 |   bool MaxMatching<Graph>::noShrinkStep(Node x, typename Graph::NodeMap<Node>& ear,  
 | 
| jacint@537 |    487 | 					UFE& blossom, UFE& tree, std::queue<Node>& Q) {
 | 
| jacint@537 |    488 |     OutEdgeIt e;
 | 
| jacint@537 |    489 |     for( G.first(e,x); G.valid(e); G.next(e) ) {
 | 
| jacint@537 |    490 |       Node y=G.bNode(e);
 | 
| jacint@537 |    491 | 	
 | 
| jacint@537 |    492 |       if ( position[y]==C ) {
 | 
| jacint@537 |    493 | 	if ( mate[y]!=INVALID ) {       //grow
 | 
| jacint@537 |    494 | 	  ear.set(y,x);
 | 
| jacint@537 |    495 | 	  Node w=mate[y];
 | 
| jacint@537 |    496 | 	  blossom.insert(w);
 | 
| jacint@537 |    497 | 	  position.set(y,A);
 | 
| jacint@537 |    498 | 	  position.set(w,D);
 | 
| jacint@537 |    499 | 	  tree.insert(y);
 | 
| jacint@537 |    500 | 	  tree.insert(w);
 | 
| jacint@537 |    501 | 	  tree.join(y,blossom.find(x));  
 | 
| jacint@537 |    502 | 	  tree.join(w,y);  
 | 
| jacint@537 |    503 | 	  Q.push(w);
 | 
| jacint@537 |    504 | 	} else {                      //augment 
 | 
| jacint@537 |    505 | 	  augment(x, ear, blossom, tree);
 | 
| jacint@537 |    506 | 	  mate.set(x,y);
 | 
| jacint@537 |    507 | 	  mate.set(y,x);
 | 
| jacint@537 |    508 | 	  return true;
 | 
| jacint@537 |    509 | 	}
 | 
| jacint@537 |    510 |       }
 | 
| jacint@537 |    511 |     }
 | 
| jacint@537 |    512 |     return false;
 | 
| jacint@537 |    513 |   }
 | 
| jacint@537 |    514 | 
 | 
| jacint@537 |    515 |   template <typename Graph>
 | 
| jacint@537 |    516 |   void MaxMatching<Graph>::shrinkStep(Node& top, Node& middle, Node& bottom, typename Graph::NodeMap<Node>& ear,  
 | 
| jacint@537 |    517 | 				      UFE& blossom, UFE& tree, std::queue<Node>& Q) {
 | 
| jacint@537 |    518 |     ear.set(top,bottom);
 | 
| jacint@537 |    519 |     Node t=top;
 | 
| jacint@537 |    520 |     while ( t!=middle ) {
 | 
| jacint@537 |    521 |       Node u=mate[t];
 | 
| jacint@537 |    522 |       t=ear[u];
 | 
| jacint@537 |    523 |       ear.set(t,u);
 | 
| jacint@537 |    524 |     } 
 | 
| jacint@537 |    525 |     bottom=mate[middle];
 | 
| jacint@537 |    526 |     position.set(bottom,D);
 | 
| jacint@537 |    527 |     Q.push(bottom);
 | 
| jacint@537 |    528 |     top=ear[bottom];		
 | 
| jacint@537 |    529 |     Node oldmiddle=middle;
 | 
| jacint@537 |    530 |     middle=blossom.find(top);
 | 
| jacint@537 |    531 |     tree.erase(bottom);
 | 
| jacint@537 |    532 |     tree.erase(oldmiddle);
 | 
| jacint@537 |    533 |     blossom.insert(bottom);
 | 
| jacint@537 |    534 |     blossom.join(bottom, oldmiddle);
 | 
| jacint@537 |    535 |     blossom.join(top, oldmiddle);
 | 
| jacint@537 |    536 |   }
 | 
| jacint@537 |    537 | 
 | 
| jacint@537 |    538 |   template <typename Graph>
 | 
| jacint@537 |    539 |   void MaxMatching<Graph>::augment(Node x, typename Graph::NodeMap<Node>& ear,  
 | 
| jacint@537 |    540 | 				   UFE& blossom, UFE& tree) { 
 | 
| jacint@537 |    541 |     Node v=mate[x];
 | 
| jacint@537 |    542 |     while ( G.valid(v) ) {
 | 
| jacint@537 |    543 | 	
 | 
| jacint@537 |    544 |       Node u=ear[v];
 | 
| jacint@537 |    545 |       mate.set(v,u);
 | 
| jacint@537 |    546 |       Node tmp=v;
 | 
| jacint@537 |    547 |       v=mate[u];
 | 
| jacint@537 |    548 |       mate.set(u,tmp);
 | 
| jacint@537 |    549 |     }
 | 
| jacint@537 |    550 |     typename UFE::ItemIt it;
 | 
| jacint@537 |    551 |     for (tree.first(it,blossom.find(x)); tree.valid(it); tree.next(it)) {   
 | 
| jacint@537 |    552 |       if ( position[it] == D ) {
 | 
| jacint@537 |    553 | 	typename UFE::ItemIt b_it;
 | 
| jacint@537 |    554 | 	for (blossom.first(b_it,it); blossom.valid(b_it); blossom.next(b_it)) {  
 | 
| jacint@537 |    555 | 	  position.set( b_it ,C);
 | 
| jacint@537 |    556 | 	}
 | 
| jacint@537 |    557 | 	blossom.eraseClass(it);
 | 
| jacint@537 |    558 |       } else position.set( it ,C);
 | 
| jacint@537 |    559 |     }
 | 
| jacint@537 |    560 |     tree.eraseClass(x);
 | 
| jacint@537 |    561 |   }
 | 
| jacint@537 |    562 | 
 | 
| jacint@537 |    563 | 
 | 
| jacint@537 |    564 | 
 | 
| jacint@537 |    565 |   /// @}
 | 
| jacint@537 |    566 |   
 | 
| alpar@921 |    567 | } //END OF NAMESPACE LEMON
 | 
| jacint@537 |    568 | 
 | 
| jacint@537 |    569 | #endif //EDMONDS_H
 |