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