| [494] | 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 |  | 
|---|