src/work/jacint/edmonds.h
author marci
Fri, 30 Apr 2004 17:10:01 +0000
changeset 499 767f3da8ce0e
permissions -rw-r--r--
A bipartite graph template can be used as BipartiteGraph<ListGraph>.
     1 // -*- C++ -*-
     2 /*
     3 Kell meg a dual oldal
     4 esetleg az elejen moho matching kereses
     5 
     6   //baj van pos-sal: nem tudok vegigmaszni a halmazok elemein. De
     7   //pos-ra nem lenne szukseg ha unionfindban lenne egy element ami
     8   //true ha benne van false ha nincs
     9 
    10 MISI strukijahoz hasznalok:
    11 
    12 void addElement(b,a): b meg nem volt egy osztalyban sem, ezzel hozzaadjuk a osztalyahoz
    13 void insert(a): a meg nem volt egy osztalyban sem, ezzel egy uj egyelemu osztalyt alkot
    14 bool element(a): true ha benne van false ha nincs
    15 void erase(a)
    16 
    17 ez a 4 a vegso szetrobbantashoz es egyideju elemfelsorolashoz kell, mas megoldas is jo ehelyett:
    18 
    19 bool empty(int i): ures-e az i nevu osztaly
    20 int find(a)
    21 void pop(int i): egy fix elso elemet kitorol az i osztalybol
    22 T top(int i): visszad egy fix elso elemet 
    23 
    24 unionfindba kene:
    25 bool element(a): true ha benne van false ha nincs  (vagy 'bool empty')
    26 void split(a) (vagy clear)
    27 T rep(a): visszaadja a halmazanak reprezentanselemet, lehet operator()-val is
    28 void makeRep(a): a-t a sajat halmazanak reprezentansava teszi
    29 
    30 Szoljatok ha nem lehet valamelyiket hatekonyan
    31 */
    32 
    33 #ifndef HUGO_EDMONDS_H
    34 #define HUGO_EDMONDS_H
    35 
    36 #include <queue>
    37 
    38 #include <invalid.h>
    39 #include <unionfind.h>
    40 
    41 namespace hugo {
    42 
    43   template <typename Graph>
    44   class Edmonds {
    45     
    46     typedef typename Graph::Node Node;
    47     typedef typename Graph::Edge Edge;
    48     typedef typename Graph::EdgeIt EdgeIt;
    49     typedef typename Graph::NodeIt NodeIt;
    50     typedef typename Graph::OutEdgeIt OutEdgeIt;
    51 
    52     typedef UnionFindEnum<Node, Graph::NodeMap > ufe;
    53             
    54     const Graph& G;
    55 
    56   public:
    57     Edmonds(Graph& _G) : G(_G) {}
    58     
    59     
    60     int run(std::vector<Edge> matching) {
    61 
    62       enum pos_enum{
    63 	D=0,
    64 	A=1,
    65 	C=2
    66       };
    67       Graph::template NodeMap<pos_enum> pos(G,C);
    68 
    69       int p=0;   //needed for path
    70 
    71       typename Graph::NodeMap<Node> mate(G,INVALID);
    72       for ( int i=0; i!=matching.size(); ++i ) {
    73 	Node u=G.aNode(matching[i]);
    74 	Node v=G.bNode(matching[i]);
    75 	mate.set(u,v);
    76 	mate.set(v,u);
    77       }
    78       matching.clear();
    79 
    80       typename Graph::NodeMap<Node> ear(G,INVALID);   
    81       // a basepontok es a C-beliek earje szemet
    82 
    83       ufe::MapType blossom_base(G);
    84       ufe blossom(blossom_base);
    85       ufe::MapType tree_base(G);
    86       ufe tree(tree_base);
    87 
    88       NodeIt v;
    89       for(G.first(v); G.valid(v), G.next(v) ) {
    90 	
    91 	if ( pos[v]==C && mate[v]=INVALID ) {
    92 	  
    93 	  blossom.insert(v);
    94 	  tree.insert(v); 
    95 	  pos.set(v,D);
    96 
    97 	  std::queue<Node> Q;   //a vizsgalando csucsok sora
    98 	  Q.push(v);  
    99 
   100 	  while ( !Q.empty() ) {
   101 	    Node x=Q.top();
   102 	    Q.pop();
   103 	    
   104 	    OutEdgeIt e;
   105 	    for( G.first(e); G.valid(e), G.next(e) ) {
   106 	      Node y=G.bNode(e);
   107 
   108 	      if ( pos[y]==D ) { 
   109 
   110 		if ( tree.find(x) != tree.find(y) ) {  //augment 
   111 		  augment(x, mate, ear, blossom, tree); 
   112 		  augment(y, mate, ear, blossom, tree); 
   113 		  mate.set(x)=y;
   114 		  mate.set(y)=x;
   115 		  goto increased;
   116 		} else 
   117 		  if ( blossom.find(x) != blossom.find(y) ) {
   118 
   119 		    typename Graph::NodeMap<int> path(G,0);
   120 
   121 		    ++p;
   122 		    Node b=blossom.find(x);
   123 		    path.set(b,p);
   124 		    while ( b!=INVALID ) {
   125 		      b=blossom.find(ear[mate[b]]);
   126 		      path.set(b,p);
   127 		    }          //going till the root
   128 	
   129 		    Node w=y;
   130 		    Node v=blossom.find(w);
   131 		    while ( path[v]!=p ) {		      
   132 		      Q.push(mate[v]);
   133 		      w=shrink_step(w,v,mate,ear,tree,blossom);
   134 		      v=blossom.find(w);
   135 		    }
   136 		    //now v is the base of the first common ancestor
   137 
   138 		    w=x;
   139 		    Node z=blossom.find(w);
   140 		    while ( z!=v ) {
   141 		      Q.push(mate[z]);
   142 		      w=shrink_step(w,z,mate,ear,tree,blossom);
   143 		      z=blossom.find(w);
   144 		    }
   145 
   146 		    ear.set(x,y);
   147 		    ear.set(y,x);
   148 
   149 		    blossom.makeRep(v);
   150 		  }
   151 	      } else if ( pos[y] == C ) 
   152 		
   153 		if ( mate[y]!=INVALID ) {       //grow
   154 		  ear.set(y,x);
   155 		  Node w=mate(y);
   156 		  blossom.insert(w);
   157 		  tree.insert(w);
   158 		  tree.join(y,x);  
   159 		  tree.join(w,x);  
   160 		  Q.push(w);
   161 		} else {
   162 		  augment(x, mate, ear, blossom, tree); 
   163 		  mate.set(x)=y;
   164 		  mate.set(y)=x;
   165 		  goto increased;
   166 		}
   167 	    }
   168 	  }
   169 	increased:  //Misi, warningol, hogy nincs utasitas!
   170 	}
   171       }
   172 
   173       int s=0;
   174       NodeIt v;
   175       for(G.first(v); G.valid(v), G.next(v) ) 
   176 	if ( mate[v]!=INVALID ) ++s;
   177 	
   178       return (int)(s/2);
   179 
   180       //egyelore nem ad semmit vissza
   181       
   182     }
   183   
   184 
   185     void augment(const Node x, typename Graph::NodeMap<Node>& mate, 
   186 		 typename Graph::NodeMap<Node>& ear, 
   187 		 ufe& blossom, ufe& tree) { 
   188       Node v=mate[x];
   189       while ( v!=INVALID ) {
   190 	Node u=ear[v];
   191 	mate.set(v,u);
   192 	Node tmp=v;
   193 	v=mate[u];
   194 	mate.set(u,tmp);
   195       }
   196       //FIXME, blossom szetszed
   197       tree.eraseClass(x);
   198     }
   199 
   200 
   201     Node shrink_step(const Node z, const Node v, typename Graph::NodeMap<Node>& mate, 
   202 		     typename Graph::NodeMap<Node>& ear, 
   203 		     ufe& blossom, ufe& tree) {  
   204       if ( z!=v ) {
   205 	Node t=z;
   206 	Node u;
   207 	while ( t!=v ) {
   208 	  u=mate[t];
   209 	  t=ear[u];
   210 	}
   211 	ear.set(v,u);
   212       }
   213 
   214       Node u=mate[v];
   215       Node w=ear[u];
   216       tree.erase(u);
   217       tree.erase(v);
   218       blossom.insert(u);
   219       blossom.join(u,w);
   220       blossom.join(v,w);
   221       ear.set(w,u);      
   222 
   223       return w;
   224     }
   225 
   226 
   227   };
   228 
   229 } //namespace hugo
   230 
   231 #endif //EDMONDS_H
   232 
   233 
   234 
   235