|
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 |