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