|
1 // -*- C++ -*- |
|
2 /* |
|
3 preflow_push_hl.hh |
|
4 by jacint. |
|
5 Runs the highest label variant of the preflow push algorithm with |
|
6 running time O(n^2\sqrt(m)). |
|
7 |
|
8 Member functions: |
|
9 |
|
10 void run() : runs the algorithm |
|
11 |
|
12 The following functions should be used after run() was already run. |
|
13 |
|
14 T maxflow() : returns the value of a maximum flow |
|
15 |
|
16 T flowonEdge(Edge_iterator e) : for a fixed maximum flow x it returns x(e) |
|
17 |
|
18 EdgeMap<graph_type, T> allflow() : returns the fixed maximum flow x |
|
19 |
|
20 NodeMap<graph_type, bool> mincut() : returns a |
|
21 characteristic vector of a minimum cut. (An empty level |
|
22 in the algorithm gives a minimum cut.) |
|
23 */ |
|
24 |
|
25 #ifndef PREFLOW_PUSH_HL_H |
|
26 #define PREFLOW_PUSH_HL_H |
|
27 |
|
28 #include <algorithm> |
|
29 #include <vector> |
|
30 #include <stack> |
|
31 |
|
32 #include <reverse_bfs.hh> |
|
33 |
|
34 namespace marci { |
|
35 |
|
36 template <typename Graph, typename T, typename FlowMap, typename CapacityMap> |
|
37 class preflow_push_hl { |
|
38 |
|
39 typedef typename Graph::NodeIt NodeIt; |
|
40 typedef typename Graph::EdgeIt EdgeIt; |
|
41 typedef typename Graph::EachNodeIt EachNodeIt; |
|
42 typedef typename Graph::OutEdgeIt OutEdgeIt; |
|
43 typedef typename Graph::InEdgeIt InEdgeIt; |
|
44 typedef typename Graph::EachEdgeIt EachEdgeIt; |
|
45 |
|
46 |
|
47 Graph& G; |
|
48 NodeIt s; |
|
49 NodeIt t; |
|
50 Graph::EdgeMap<T> flow; |
|
51 Graph::EdgeMap<T> capacity; |
|
52 T value; |
|
53 Graph::NodeMap<bool> mincutvector; |
|
54 |
|
55 |
|
56 public: |
|
57 |
|
58 preflow_push_hl(Graph& _G, NodeIt _s, NodeIt _t, |
|
59 Graph::EdgeMap<T>& _capacity) : |
|
60 G(_G), s(_s), t(_t), flow(_G, 0), capacity(_capacity), mincutvector(_G, true) { } |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 /* |
|
66 The run() function runs the highest label preflow-push, |
|
67 running time: O(n^2\sqrt(m)) |
|
68 */ |
|
69 void run() { |
|
70 |
|
71 Graph::NodeMap<int> level(G); //level of Node |
|
72 Graph::NodeMap<T> excess(G); //excess of Node |
|
73 |
|
74 int n=G.nodeNum(); //number of Nodes |
|
75 int b=n; |
|
76 /*b is a bound on the highest level of an active Node. In the beginning it is at most n-2.*/ |
|
77 |
|
78 std::vector<std::stack<NodeIt> > stack(2*n-1); //Stack of the active Nodes in level i. |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 /*Reverse_bfs from t, to find the starting level.*/ |
|
84 |
|
85 reverse_bfs<list_graph> bfs(G, t); |
|
86 bfs.run(); |
|
87 for(EachNodeIt v=G.template first<EachNodeIt>(); v.valid(); ++v) { |
|
88 level.set(v, bfs.dist(v)); |
|
89 //std::cout << "the level of " << v << " is " << bfs.dist(v); |
|
90 } |
|
91 |
|
92 /*The level of s is fixed to n*/ |
|
93 level.set(s,n); |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 /* Starting flow. It is everywhere 0 at the moment. */ |
|
100 |
|
101 for(OutEdgeIt i=G.template first<OutEdgeIt>(s); i.valid(); ++i) |
|
102 { |
|
103 NodeIt w=G.head(i); |
|
104 flow.set(i, capacity.get(i)); |
|
105 stack[bfs.dist(w)].push(w); |
|
106 excess.set(w, capacity.get(i)); |
|
107 } |
|
108 |
|
109 |
|
110 /* |
|
111 End of preprocessing |
|
112 */ |
|
113 |
|
114 |
|
115 |
|
116 /* |
|
117 Push/relabel on the highest level active Nodes. |
|
118 */ |
|
119 |
|
120 /*While there exists active Node.*/ |
|
121 while (b) { |
|
122 |
|
123 /*We decrease the bound if there is no active Node of level b.*/ |
|
124 if (stack[b].empty()) { |
|
125 --b; |
|
126 } else { |
|
127 |
|
128 NodeIt w=stack[b].top(); //w is the highest label active Node. |
|
129 stack[b].pop(); //We delete w from the stack. |
|
130 |
|
131 int newlevel=2*n-2; //In newlevel we maintain the next level of w. |
|
132 |
|
133 for(OutEdgeIt e=G.template first<OutEdgeIt>(w); e.valid(); ++e) { |
|
134 NodeIt v=G.head(e); |
|
135 /*e is the Edge wv.*/ |
|
136 |
|
137 if (flow.get(e)<capacity.get(e)) { |
|
138 /*e is an Edge of the residual graph */ |
|
139 |
|
140 if(level.get(w)==level.get(v)+1) { |
|
141 /*Push is allowed now*/ |
|
142 |
|
143 if (capacity.get(e)-flow.get(e) > excess.get(w)) { |
|
144 /*A nonsaturating push.*/ |
|
145 |
|
146 if (excess.get(v)==0 && v != s) stack[level.get(v)].push(v); |
|
147 /*v becomes active.*/ |
|
148 |
|
149 flow.set(e, flow.get(e)+excess.get(w)); |
|
150 excess.set(v, excess.get(v)+excess.get(w)); |
|
151 excess.set(w,0); |
|
152 //std::cout << w << " " << v <<" elore elen nonsat pump " << std::endl; |
|
153 break; |
|
154 } else { |
|
155 /*A saturating push.*/ |
|
156 |
|
157 if (excess.get(v)==0 && v != s) stack[level.get(v)].push(v); |
|
158 /*v becomes active.*/ |
|
159 |
|
160 excess.set(v, excess.get(v)+capacity.get(e)-flow.get(e)); |
|
161 excess.set(w, excess.get(w)-capacity.get(e)+flow.get(e)); |
|
162 flow.set(e, capacity.get(e)); |
|
163 //std::cout << w<<" " <<v<<" elore elen sat pump " << std::endl; |
|
164 if (excess.get(w)==0) break; |
|
165 /*If w is not active any more, then we go on to the next Node.*/ |
|
166 |
|
167 } // if (capacity.get(e)-flow.get(e) > excess.get(w)) |
|
168 } // if(level.get(w)==level.get(v)+1) |
|
169 |
|
170 else {newlevel = newlevel < level.get(v) ? newlevel : level.get(v);} |
|
171 |
|
172 } //if (flow.get(e)<capacity.get(e)) |
|
173 |
|
174 } //for(OutEdgeIt e=G.first_OutEdge(w); e.valid(); ++e) |
|
175 |
|
176 |
|
177 |
|
178 for(InEdgeIt e=G.template first<InEdgeIt>(w); e.valid(); ++e) { |
|
179 NodeIt v=G.tail(e); |
|
180 /*e is the Edge vw.*/ |
|
181 |
|
182 if (excess.get(w)==0) break; |
|
183 /*It may happen, that w became inactive in the first for cycle.*/ |
|
184 if(flow.get(e)>0) { |
|
185 /*e is an Edge of the residual graph */ |
|
186 |
|
187 if(level.get(w)==level.get(v)+1) { |
|
188 /*Push is allowed now*/ |
|
189 |
|
190 if (flow.get(e) > excess.get(w)) { |
|
191 /*A nonsaturating push.*/ |
|
192 |
|
193 if (excess.get(v)==0 && v != s) stack[level.get(v)].push(v); |
|
194 /*v becomes active.*/ |
|
195 |
|
196 flow.set(e, flow.get(e)-excess.get(w)); |
|
197 excess.set(v, excess.get(v)+excess.get(w)); |
|
198 excess.set(w,0); |
|
199 //std::cout << v << " " << w << " vissza elen nonsat pump " << std::endl; |
|
200 break; |
|
201 } else { |
|
202 /*A saturating push.*/ |
|
203 |
|
204 if (excess.get(v)==0 && v != s) stack[level.get(v)].push(v); |
|
205 /*v becomes active.*/ |
|
206 |
|
207 excess.set(v, excess.get(v)+flow.get(e)); |
|
208 excess.set(w, excess.get(w)-flow.get(e)); |
|
209 flow.set(e,0); |
|
210 //std::cout << v <<" " << w << " vissza elen sat pump " << std::endl; |
|
211 if (excess.get(w)==0) { break;} |
|
212 } //if (flow.get(e) > excess.get(v)) |
|
213 } //if(level.get(w)==level.get(v)+1) |
|
214 |
|
215 else {newlevel = newlevel < level.get(v) ? newlevel : level.get(v);} |
|
216 |
|
217 |
|
218 } //if (flow.get(e)>0) |
|
219 |
|
220 } //for |
|
221 |
|
222 |
|
223 if (excess.get(w)>0) { |
|
224 level.set(w,++newlevel); |
|
225 stack[newlevel].push(w); |
|
226 b=newlevel; |
|
227 //std::cout << "The new level of " << w << " is "<< newlevel <<std::endl; |
|
228 } |
|
229 |
|
230 |
|
231 } //else |
|
232 |
|
233 } //while(b) |
|
234 |
|
235 value = excess.get(t); |
|
236 /*Max flow value.*/ |
|
237 |
|
238 |
|
239 |
|
240 |
|
241 } //void run() |
|
242 |
|
243 |
|
244 |
|
245 |
|
246 |
|
247 /* |
|
248 Returns the maximum value of a flow. |
|
249 */ |
|
250 |
|
251 T maxflow() { |
|
252 return value; |
|
253 } |
|
254 |
|
255 |
|
256 |
|
257 /* |
|
258 For the maximum flow x found by the algorithm, it returns the flow value on Edge e, i.e. x(e). |
|
259 */ |
|
260 |
|
261 T flowonEdge(EdgeIt e) { |
|
262 return flow.get(e); |
|
263 } |
|
264 |
|
265 |
|
266 |
|
267 /* |
|
268 Returns the maximum flow x found by the algorithm. |
|
269 */ |
|
270 |
|
271 EdgeMap<graph_type, T> allflow() { |
|
272 return flow; |
|
273 } |
|
274 |
|
275 |
|
276 |
|
277 /* |
|
278 Returns a minimum cut by using a reverse bfs from t in the residual graph. |
|
279 */ |
|
280 |
|
281 NodeMap<graph_type, bool> mincut() { |
|
282 |
|
283 std::queue<NodeIt> queue; |
|
284 |
|
285 mincutvector.set(t,false); |
|
286 queue.push(t); |
|
287 |
|
288 while (!queue.empty()) { |
|
289 NodeIt w=queue.front(); |
|
290 queue.pop(); |
|
291 |
|
292 for(InEdgeIt e=G.template first<InEdgeIt>(w) ; e.valid(); ++e) { |
|
293 NodeIt v=G.tail(e); |
|
294 if (mincutvector.get(v) && flow.get(e) < capacity.get(e) ) { |
|
295 queue.push(v); |
|
296 mincutvector.set(v, false); |
|
297 } |
|
298 } // for |
|
299 |
|
300 for(OutEdgeIt e=G.template first<OutEdgeIt>(w) ; e.valid(); ++e) { |
|
301 NodeIt v=G.head(e); |
|
302 if (mincutvector.get(v) && flow.get(e) > 0 ) { |
|
303 queue.push(v); |
|
304 mincutvector.set(v, false); |
|
305 } |
|
306 } // for |
|
307 |
|
308 } |
|
309 |
|
310 return mincutvector; |
|
311 |
|
312 } |
|
313 |
|
314 |
|
315 }; |
|
316 }//namespace marci |
|
317 #endif |
|
318 |
|
319 |
|
320 |
|
321 |