lemon/matching.h
changeset 1207 eba5aa390aca
parent 1092 dceba191c00d
child 1208 c6aa2cc1af04
equal deleted inserted replaced
8:eee9d14047cc 9:e050331efcec
   113     TreeSet* _tree_set;
   113     TreeSet* _tree_set;
   114 
   114 
   115     NodeQueue _node_queue;
   115     NodeQueue _node_queue;
   116     int _process, _postpone, _last;
   116     int _process, _postpone, _last;
   117 
   117 
   118     int _node_num;
   118     int _node_num, _unmatched;
   119 
   119 
   120   private:
   120   private:
   121 
   121 
   122     void createStructures() {
   122     void createStructures() {
   123       _node_num = countNodes(_graph);
   123       _node_num = countNodes(_graph);
   177           Node v = _graph.target(a);
   177           Node v = _graph.target(a);
   178           if ((*_status)[v] == MATCHED) {
   178           if ((*_status)[v] == MATCHED) {
   179             extendOnArc(a);
   179             extendOnArc(a);
   180           } else if ((*_status)[v] == UNMATCHED) {
   180           } else if ((*_status)[v] == UNMATCHED) {
   181             augmentOnArc(a);
   181             augmentOnArc(a);
       
   182             --_unmatched;
   182             return;
   183             return;
   183           }
   184           }
   184         }
   185         }
   185       }
   186       }
   186 
   187 
   202               Node x = _graph.target(b);
   203               Node x = _graph.target(b);
   203               if ((*_status)[x] == MATCHED) {
   204               if ((*_status)[x] == MATCHED) {
   204                 extendOnArc(b);
   205                 extendOnArc(b);
   205               } else if ((*_status)[x] == UNMATCHED) {
   206               } else if ((*_status)[x] == UNMATCHED) {
   206                 augmentOnArc(b);
   207                 augmentOnArc(b);
       
   208                 --_unmatched;
   207                 return;
   209                 return;
   208               }
   210               }
   209             }
   211             }
   210           }
   212           }
   211         }
   213         }
   226             }
   228             }
   227           } else if ((*_status)[v] == MATCHED) {
   229           } else if ((*_status)[v] == MATCHED) {
   228             extendOnArc(a);
   230             extendOnArc(a);
   229           } else if ((*_status)[v] == UNMATCHED) {
   231           } else if ((*_status)[v] == UNMATCHED) {
   230             augmentOnArc(a);
   232             augmentOnArc(a);
       
   233             --_unmatched;
   231             return;
   234             return;
   232           }
   235           }
   233         }
   236         }
   234       }
   237       }
   235     }
   238     }
   435       createStructures();
   438       createStructures();
   436       for(NodeIt n(_graph); n != INVALID; ++n) {
   439       for(NodeIt n(_graph); n != INVALID; ++n) {
   437         (*_matching)[n] = INVALID;
   440         (*_matching)[n] = INVALID;
   438         (*_status)[n] = UNMATCHED;
   441         (*_status)[n] = UNMATCHED;
   439       }
   442       }
       
   443       _unmatched = _node_num;
   440     }
   444     }
   441 
   445 
   442     /// \brief Find an initial matching in a greedy way.
   446     /// \brief Find an initial matching in a greedy way.
   443     ///
   447     ///
   444     /// This function finds an initial matching in a greedy way.
   448     /// This function finds an initial matching in a greedy way.
   446       createStructures();
   450       createStructures();
   447       for (NodeIt n(_graph); n != INVALID; ++n) {
   451       for (NodeIt n(_graph); n != INVALID; ++n) {
   448         (*_matching)[n] = INVALID;
   452         (*_matching)[n] = INVALID;
   449         (*_status)[n] = UNMATCHED;
   453         (*_status)[n] = UNMATCHED;
   450       }
   454       }
       
   455       _unmatched = _node_num;
   451       for (NodeIt n(_graph); n != INVALID; ++n) {
   456       for (NodeIt n(_graph); n != INVALID; ++n) {
   452         if ((*_matching)[n] == INVALID) {
   457         if ((*_matching)[n] == INVALID) {
   453           for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
   458           for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
   454             Node v = _graph.target(a);
   459             Node v = _graph.target(a);
   455             if ((*_matching)[v] == INVALID && v != n) {
   460             if ((*_matching)[v] == INVALID && v != n) {
   456               (*_matching)[n] = a;
   461               (*_matching)[n] = a;
   457               (*_status)[n] = MATCHED;
   462               (*_status)[n] = MATCHED;
   458               (*_matching)[v] = _graph.oppositeArc(a);
   463               (*_matching)[v] = _graph.oppositeArc(a);
   459               (*_status)[v] = MATCHED;
   464               (*_status)[v] = MATCHED;
       
   465               _unmatched -= 2;
   460               break;
   466               break;
   461             }
   467             }
   462           }
   468           }
   463         }
   469         }
   464       }
   470       }
   477 
   483 
   478       for (NodeIt n(_graph); n != INVALID; ++n) {
   484       for (NodeIt n(_graph); n != INVALID; ++n) {
   479         (*_matching)[n] = INVALID;
   485         (*_matching)[n] = INVALID;
   480         (*_status)[n] = UNMATCHED;
   486         (*_status)[n] = UNMATCHED;
   481       }
   487       }
       
   488       _unmatched = _node_num;
   482       for(EdgeIt e(_graph); e!=INVALID; ++e) {
   489       for(EdgeIt e(_graph); e!=INVALID; ++e) {
   483         if (matching[e]) {
   490         if (matching[e]) {
   484 
   491 
   485           Node u = _graph.u(e);
   492           Node u = _graph.u(e);
   486           if ((*_matching)[u] != INVALID) return false;
   493           if ((*_matching)[u] != INVALID) return false;
   489 
   496 
   490           Node v = _graph.v(e);
   497           Node v = _graph.v(e);
   491           if ((*_matching)[v] != INVALID) return false;
   498           if ((*_matching)[v] != INVALID) return false;
   492           (*_matching)[v] = _graph.direct(e, false);
   499           (*_matching)[v] = _graph.direct(e, false);
   493           (*_status)[v] = MATCHED;
   500           (*_status)[v] = MATCHED;
       
   501 
       
   502           _unmatched -= 2;
   494         }
   503         }
   495       }
   504       }
   496       return true;
   505       return true;
   497     }
   506     }
   498 
   507 
   499     /// \brief Start Edmonds' algorithm
   508     /// \brief Start Edmonds' algorithm
   500     ///
   509     ///
   501     /// This function runs the original Edmonds' algorithm.
   510     /// This function runs the original Edmonds' algorithm. If the
       
   511     /// \c decomposition parameter is set to false, then the Gallai-Edmonds
       
   512     /// decomposition is not computed.
   502     ///
   513     ///
   503     /// \pre \ref init(), \ref greedyInit() or \ref matchingInit() must be
   514     /// \pre \ref init(), \ref greedyInit() or \ref matchingInit() must be
   504     /// called before using this function.
   515     /// called before using this function.
   505     void startSparse() {
   516     void startSparse(bool decomposition = true) {
   506       for(NodeIt n(_graph); n != INVALID; ++n) {
   517       int _unmatched_limit = decomposition ? 0 : 1;
       
   518       for(NodeIt n(_graph); _unmatched > _unmatched_limit; ++n) {
   507         if ((*_status)[n] == UNMATCHED) {
   519         if ((*_status)[n] == UNMATCHED) {
   508           (*_blossom_rep)[_blossom_set->insert(n)] = n;
   520           (*_blossom_rep)[_blossom_set->insert(n)] = n;
   509           _tree_set->insert(n);
   521           _tree_set->insert(n);
   510           (*_status)[n] = EVEN;
   522           (*_status)[n] = EVEN;
       
   523           --_unmatched;
   511           processSparse(n);
   524           processSparse(n);
   512         }
   525         }
   513       }
   526       }
   514     }
   527     }
   515 
   528 
   516     /// \brief Start Edmonds' algorithm with a heuristic improvement
   529     /// \brief Start Edmonds' algorithm with a heuristic improvement
   517     /// for dense graphs
   530     /// for dense graphs
   518     ///
   531     ///
   519     /// This function runs Edmonds' algorithm with a heuristic of postponing
   532     /// This function runs Edmonds' algorithm with a heuristic of postponing
   520     /// shrinks, therefore resulting in a faster algorithm for dense graphs.
   533     /// shrinks, therefore resulting in a faster algorithm for dense graphs.  If
       
   534     /// the \c decomposition parameter is set to false, then the Gallai-Edmonds
       
   535     /// decomposition is not computed.
   521     ///
   536     ///
   522     /// \pre \ref init(), \ref greedyInit() or \ref matchingInit() must be
   537     /// \pre \ref init(), \ref greedyInit() or \ref matchingInit() must be
   523     /// called before using this function.
   538     /// called before using this function.
   524     void startDense() {
   539     void startDense(bool decomposition = true) {
   525       for(NodeIt n(_graph); n != INVALID; ++n) {
   540       int _unmatched_limit = decomposition ? 0 : 1;
       
   541       for(NodeIt n(_graph); _unmatched > _unmatched_limit; ++n) {
   526         if ((*_status)[n] == UNMATCHED) {
   542         if ((*_status)[n] == UNMATCHED) {
   527           (*_blossom_rep)[_blossom_set->insert(n)] = n;
   543           (*_blossom_rep)[_blossom_set->insert(n)] = n;
   528           _tree_set->insert(n);
   544           _tree_set->insert(n);
   529           (*_status)[n] = EVEN;
   545           (*_status)[n] = EVEN;
       
   546           --_unmatched;
   530           processDense(n);
   547           processDense(n);
   531         }
   548         }
   532       }
   549       }
   533     }
   550     }
   534 
   551 
   535 
   552 
   536     /// \brief Run Edmonds' algorithm
   553     /// \brief Run Edmonds' algorithm
   537     ///
   554     ///
   538     /// This function runs Edmonds' algorithm. An additional heuristic of
   555     /// This function runs Edmonds' algorithm. An additional heuristic of
   539     /// postponing shrinks is used for relatively dense graphs
   556     /// postponing shrinks is used for relatively dense graphs (for which
   540     /// (for which <tt>m>=2*n</tt> holds).
   557     /// <tt>m>=2*n</tt> holds). If the \c decomposition parameter is set to
   541     void run() {
   558     /// false, then the Gallai-Edmonds decomposition is not computed. In some
       
   559     /// cases, this can speed up the algorithm significantly, especially when a
       
   560     /// maximum matching is computed in a dense graph with odd number of nodes.
       
   561     void run(bool decomposition = true) {
   542       if (countEdges(_graph) < 2 * countNodes(_graph)) {
   562       if (countEdges(_graph) < 2 * countNodes(_graph)) {
   543         greedyInit();
   563         greedyInit();
   544         startSparse();
   564         startSparse(decomposition);
   545       } else {
   565       } else {
   546         init();
   566         init();
   547         startDense();
   567         startDense(decomposition);
   548       }
   568       }
   549     }
   569     }
   550 
   570 
   551     /// @}
   571     /// @}
   552 
   572