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