/* -*- C++ -*- * * This file is a part of LEMON, a generic C++ optimization library * * Copyright (C) 2003-2007 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Research Group on Combinatorial Optimization, EGRES). * * Permission to use, modify and distribute this software is granted * provided that this copyright notice appears in all copies. For * precise terms see the accompanying LICENSE file. * * This software is provided "AS IS" with no warranty of any kind, * express or implied, and with no claim as to its suitability for any * purpose. * */ #ifndef LEMON_BP_MATCHING #define LEMON_BP_MATCHING #include #include #include #include #include #include ///\ingroup matching ///\file ///\brief Push-prelabel maximum matching algorithms in bipartite graphs. /// ///\todo This file slightly conflicts with \ref lemon/bipartite_matching.h ///\todo (Re)move the XYZ_TYPEDEFS macros namespace lemon { #define BIPARTITE_TYPEDEFS(Graph) \ GRAPH_TYPEDEFS(Graph) \ typedef Graph::ANodeIt ANodeIt; \ typedef Graph::BNodeIt BNodeIt; #define UNDIRBIPARTITE_TYPEDEFS(Graph) \ UNDIRGRAPH_TYPEDEFS(Graph) \ typedef Graph::ANodeIt ANodeIt; \ typedef Graph::BNodeIt BNodeIt; template > class BpMatching { typedef typename Graph::Node Node; typedef typename Graph::ANodeIt ANodeIt; typedef typename Graph::BNodeIt BNodeIt; typedef typename Graph::UEdge UEdge; typedef typename Graph::IncEdgeIt IncEdgeIt; const Graph &_g; int _node_num; MT &_matching; Elevator _levels; typename Graph::template BNodeMap _cov; public: BpMatching(const Graph &g, MT &matching) : _g(g), _node_num(countBNodes(g)), _matching(matching), _levels(g,_node_num), _cov(g,0) { } private: void init() { // for(BNodeIt n(g);n!=INVALID;++n) cov[n]=0; for(ANodeIt n(_g);n!=INVALID;++n) if((_matching[n]=IncEdgeIt(_g,n))!=INVALID) ++_cov[_g.oppositeNode(n,_matching[n])]; std::queue q; _levels.initStart(); for(BNodeIt n(_g);n!=INVALID;++n) if(_cov[n]>1) { _levels.initAddItem(n); q.push(n); } int hlev=0; while(!q.empty()) { Node n=q.front(); q.pop(); int nlev=_levels[n]+1; for(IncEdgeIt e(_g,n);e!=INVALID;++e) { Node m=_g.runningNode(e); if(e==_matching[m]) { for(IncEdgeIt f(_g,m);f!=INVALID;++f) { Node r=_g.runningNode(f); if(_levels[r]>nlev) { for(;nlev>hlev;hlev++) _levels.initNewLevel(); _levels.initAddItem(r); q.push(r); } } } } } _levels.initFinish(); for(BNodeIt n(_g);n!=INVALID;++n) if(_cov[n]<1&&_levels[n]<_node_num) _levels.activate(n); } public: int run() { init(); Node act; Node bact=INVALID; Node last_activated=INVALID; // while((act=last_activated!=INVALID? // last_activated:_levels.highestActive()) // !=INVALID) while((act=_levels.highestActive())!=INVALID) { last_activated=INVALID; int actlevel=_levels[act]; UEdge bedge=INVALID; int nlevel=_node_num; { int nnlevel; for(IncEdgeIt tbedge(_g,act); tbedge!=INVALID && nlevel>=actlevel; ++tbedge) if((nnlevel=_levels[_g.bNode(_matching[_g.runningNode(tbedge)])])< nlevel) { nlevel=nnlevel; bedge=tbedge; } } if(nlevel<_node_num) { if(nlevel>=actlevel) _levels.liftHighestActiveTo(nlevel+1); // _levels.liftTo(act,nlevel+1); bact=_g.bNode(_matching[_g.aNode(bedge)]); if(--_cov[bact]<1) { _levels.activate(bact); last_activated=bact; } _matching[_g.aNode(bedge)]=bedge; _cov[act]=1; _levels.deactivate(act); } else { if(_node_num>actlevel) _levels.liftHighestActiveTo(_node_num); // _levels.liftTo(act,_node_num); _levels.deactivate(act); } if(_levels.onLevel(actlevel)==0) _levels.liftToTop(actlevel); } int ret=_node_num; for(ANodeIt n(_g);n!=INVALID;++n) if(_matching[n]==INVALID) ret--; else if (_cov[_g.bNode(_matching[n])]>1) { _cov[_g.bNode(_matching[n])]--; ret--; _matching[n]=INVALID; } return ret; } ///\returns -1 if there is a perfect matching, or an empty level ///if it doesn't exists int runPerfect() { init(); Node act; Node bact=INVALID; Node last_activated=INVALID; while((act=_levels.highestActive())!=INVALID) { last_activated=INVALID; int actlevel=_levels[act]; UEdge bedge=INVALID; int nlevel=_node_num; { int nnlevel; for(IncEdgeIt tbedge(_g,act); tbedge!=INVALID && nlevel>=actlevel; ++tbedge) if((nnlevel=_levels[_g.bNode(_matching[_g.runningNode(tbedge)])])< nlevel) { nlevel=nnlevel; bedge=tbedge; } } if(nlevel<_node_num) { if(nlevel>=actlevel) _levels.liftHighestActiveTo(nlevel+1); bact=_g.bNode(_matching[_g.aNode(bedge)]); if(--_cov[bact]<1) { _levels.activate(bact); last_activated=bact; } _matching[_g.aNode(bedge)]=bedge; _cov[act]=1; _levels.deactivate(act); } else { if(_node_num>actlevel) _levels.liftHighestActiveTo(_node_num); _levels.deactivate(act); } if(_levels.onLevel(actlevel)==0) return actlevel; } return -1; } template void aBarrier(GT &bar,int empty_level=-1) { if(empty_level==-1) for(empty_level=0;_levels.onLevel(empty_level);empty_level++) ; for(ANodeIt n(_g);n!=INVALID;++n) bar[n] = _matching[n]==INVALID || _levels[_g.bNode(_matching[n])] void bBarrier(GT &bar, int empty_level=-1) { if(empty_level==-1) for(empty_level=0;_levels.onLevel(empty_level);empty_level++) ; for(BNodeIt n(_g);n!=INVALID;++n) bar[n]=(_levels[n]>empty_level); } }; ///Maximum cardinality of the matchings in a bipartite graph ///\ingroup matching ///This function finds the maximum cardinality of the matchings ///in a bipartite graph \c g. ///\param g An undirected bipartite graph. ///\return The cardinality of the maximum matching. /// ///\note The the implementation is based ///on the push-relabel principle. template int maxBpMatching(const Graph &g) { typename Graph::template ANodeMap matching(g); return maxBpMatching(g,matching); } ///Maximum cardinality matching in a bipartite graph ///\ingroup matching ///This function finds a maximum cardinality matching ///in a bipartite graph \c g. ///\param g An undirected bipartite graph. ///\retval matching A readwrite ANodeMap of value type \c Edge. /// The found edges will be returned in this map, /// i.e. for an \c ANode \c n, /// the edge matching[n] is the one that covers the node \c n, or /// \ref INVALID if it is uncovered. ///\return The cardinality of the maximum matching. /// ///\note The the implementation is based ///on the push-relabel principle. template int maxBpMatching(const Graph &g,MT &matching) { return BpMatching(g,matching).run(); } ///Maximum cardinality matching in a bipartite graph ///\ingroup matching ///This function finds a maximum cardinality matching ///in a bipartite graph \c g. ///\param g An undirected bipartite graph. ///\retval matching A readwrite ANodeMap of value type \c Edge. /// The found edges will be returned in this map, /// i.e. for an \c ANode \c n, /// the edge matching[n] is the one that covers the node \c n, or /// \ref INVALID if it is uncovered. ///\retval barrier A \c bool WriteMap on the BNodes. The map will be set /// exactly once for each BNode. The nodes with \c true value represent /// a barrier \e B, i.e. the cardinality of \e B minus the number of its /// neighbor is equal to the number of the BNodes minus the /// cardinality of the maximum matching. ///\return The cardinality of the maximum matching. /// ///\note The the implementation is based ///on the push-relabel principle. template int maxBpMatching(const Graph &g,MT &matching,GT &barrier) { BpMatching bpm(g,matching); int ret=bpm.run(); bpm.barrier(barrier); return ret; } ///Perfect matching in a bipartite graph ///\ingroup matching ///This function checks whether the bipartite graph \c g ///has a perfect matching. ///\param g An undirected bipartite graph. ///\return \c true iff \c g has a perfect matching. /// ///\note The the implementation is based ///on the push-relabel principle. template bool perfectBpMatching(const Graph &g) { typename Graph::template ANodeMap matching(g); return perfectBpMatching(g,matching); } ///Perfect matching in a bipartite graph ///\ingroup matching ///This function finds a perfect matching in a bipartite graph \c g. ///\param g An undirected bipartite graph. ///\retval matching A readwrite ANodeMap of value type \c Edge. /// The found edges will be returned in this map, /// i.e. for an \c ANode \c n, /// the edge matching[n] is the one that covers the node \c n. /// The values are unspecified if the graph /// has no perfect matching. ///\return \c true iff \c g has a perfect matching. /// ///\note The the implementation is based ///on the push-relabel principle. template bool perfectBpMatching(const Graph &g,MT &matching) { return BpMatching(g,matching).runPerfect()<0; } ///Perfect matching in a bipartite graph ///\ingroup matching ///This function finds a perfect matching in a bipartite graph \c g. ///\param g An undirected bipartite graph. ///\retval matching A readwrite ANodeMap of value type \c Edge. /// The found edges will be returned in this map, /// i.e. for an \c ANode \c n, /// the edge matching[n] is the one that covers the node \c n. /// The values are unspecified if the graph /// has no perfect matching. ///\retval barrier A \c bool WriteMap on the BNodes. The map will only /// be set if \c g has no perfect matching. In this case it is set /// exactly once for each BNode. The nodes with \c true value represent /// a barrier, i.e. a subset \e B a of BNodes with the property that /// the cardinality of \e B is greater than the numner of its neighbors. ///\return \c true iff \c g has a perfect matching. /// ///\note The the implementation is based ///on the push-relabel principle. template int perfectBpMatching(const Graph &g,MT &matching,GT &barrier) { BpMatching bpm(g,matching); int ret=bpm.run(); if(ret>=0) bpm.barrier(barrier,ret); return ret<0; } } #endif