marci@762
|
1 |
// -*- C++ -*-
|
alpar@921
|
2 |
#ifndef LEMON_AUGMENTING_FLOW_H
|
alpar@921
|
3 |
#define LEMON_AUGMENTING_FLOW_H
|
marci@762
|
4 |
|
marci@762
|
5 |
#include <vector>
|
marci@762
|
6 |
#include <iostream>
|
marci@762
|
7 |
|
alpar@921
|
8 |
#include <lemon/graph_wrapper.h>
|
marci@944
|
9 |
//#include <bfs_dfs.h>
|
marci@944
|
10 |
#include <bfs_mm.h>
|
alpar@921
|
11 |
#include <lemon/invalid.h>
|
alpar@921
|
12 |
#include <lemon/maps.h>
|
marci@944
|
13 |
#include <demo/tight_edge_filter_map.h>
|
marci@762
|
14 |
|
marci@762
|
15 |
/// \file
|
marci@762
|
16 |
/// \brief Maximum flow algorithms.
|
marci@762
|
17 |
/// \ingroup galgs
|
marci@762
|
18 |
|
alpar@921
|
19 |
namespace lemon {
|
marci@944
|
20 |
using lemon::marci::BfsIterator;
|
marci@944
|
21 |
using lemon::marci::DfsIterator;
|
marci@762
|
22 |
|
marci@762
|
23 |
/// \addtogroup galgs
|
marci@762
|
24 |
/// @{
|
marci@862
|
25 |
/// Class for augmenting path flow algorithms.
|
marci@762
|
26 |
|
marci@862
|
27 |
/// This class provides various algorithms for finding a flow of
|
marci@862
|
28 |
/// maximum value in a directed graph. The \e source node, the \e
|
marci@862
|
29 |
/// target node, the \e capacity of the edges and the \e starting \e
|
marci@862
|
30 |
/// flow value of the edges should be passed to the algorithm through the
|
marci@862
|
31 |
/// constructor.
|
marci@862
|
32 |
// /// It is possible to change these quantities using the
|
marci@862
|
33 |
// /// functions \ref resetSource, \ref resetTarget, \ref resetCap and
|
marci@862
|
34 |
// /// \ref resetFlow. Before any subsequent runs of any algorithm of
|
marci@862
|
35 |
// /// the class \ref resetFlow should be called.
|
marci@762
|
36 |
|
marci@862
|
37 |
/// After running an algorithm of the class, the actual flow value
|
marci@862
|
38 |
/// can be obtained by calling \ref flowValue(). The minimum
|
marci@862
|
39 |
/// value cut can be written into a \c node map of \c bools by
|
marci@862
|
40 |
/// calling \ref minCut. (\ref minMinCut and \ref maxMinCut writes
|
marci@862
|
41 |
/// the inclusionwise minimum and maximum of the minimum value
|
marci@862
|
42 |
/// cuts, resp.)
|
marci@762
|
43 |
///\param Graph The directed graph type the algorithm runs on.
|
marci@762
|
44 |
///\param Num The number type of the capacities and the flow values.
|
marci@762
|
45 |
///\param CapMap The capacity map type.
|
marci@762
|
46 |
///\param FlowMap The flow map type.
|
marci@862
|
47 |
///\author Marton Makai
|
marci@762
|
48 |
template <typename Graph, typename Num,
|
marci@762
|
49 |
typename CapMap=typename Graph::template EdgeMap<Num>,
|
marci@762
|
50 |
typename FlowMap=typename Graph::template EdgeMap<Num> >
|
marci@762
|
51 |
class AugmentingFlow {
|
marci@762
|
52 |
protected:
|
marci@762
|
53 |
typedef typename Graph::Node Node;
|
marci@762
|
54 |
typedef typename Graph::NodeIt NodeIt;
|
marci@762
|
55 |
typedef typename Graph::EdgeIt EdgeIt;
|
marci@762
|
56 |
typedef typename Graph::OutEdgeIt OutEdgeIt;
|
marci@762
|
57 |
typedef typename Graph::InEdgeIt InEdgeIt;
|
marci@762
|
58 |
|
marci@762
|
59 |
const Graph* g;
|
marci@762
|
60 |
Node s;
|
marci@762
|
61 |
Node t;
|
marci@762
|
62 |
const CapMap* capacity;
|
marci@762
|
63 |
FlowMap* flow;
|
marci@762
|
64 |
// int n; //the number of nodes of G
|
marci@762
|
65 |
typedef ResGraphWrapper<const Graph, Num, CapMap, FlowMap> ResGW;
|
marci@762
|
66 |
//typedef ExpResGraphWrapper<const Graph, Num, CapMap, FlowMap> ResGW;
|
marci@762
|
67 |
typedef typename ResGW::OutEdgeIt ResGWOutEdgeIt;
|
marci@762
|
68 |
typedef typename ResGW::Edge ResGWEdge;
|
marci@762
|
69 |
//typedef typename ResGW::template NodeMap<bool> ReachedMap;
|
marci@762
|
70 |
typedef typename Graph::template NodeMap<int> ReachedMap;
|
marci@762
|
71 |
|
marci@762
|
72 |
//level works as a bool map in augmenting path algorithms and is
|
marci@762
|
73 |
//used by bfs for storing reached information. In preflow, it
|
marci@762
|
74 |
//shows the levels of nodes.
|
marci@762
|
75 |
ReachedMap level;
|
marci@762
|
76 |
|
marci@762
|
77 |
public:
|
marci@762
|
78 |
///Indicates the property of the starting flow.
|
marci@762
|
79 |
|
marci@762
|
80 |
///Indicates the property of the starting flow. The meanings are as follows:
|
marci@762
|
81 |
///- \c ZERO_FLOW: constant zero flow
|
marci@762
|
82 |
///- \c GEN_FLOW: any flow, i.e. the sum of the in-flows equals to
|
marci@762
|
83 |
///the sum of the out-flows in every node except the \e source and
|
marci@762
|
84 |
///the \e target.
|
marci@762
|
85 |
///- \c PRE_FLOW: any preflow, i.e. the sum of the in-flows is at
|
marci@762
|
86 |
///least the sum of the out-flows in every node except the \e source.
|
marci@762
|
87 |
///- \c NO_FLOW: indicates an unspecified edge map. \ref flow will be
|
marci@762
|
88 |
///set to the constant zero flow in the beginning of the algorithm in this case.
|
marci@762
|
89 |
enum FlowEnum{
|
marci@762
|
90 |
ZERO_FLOW,
|
marci@762
|
91 |
GEN_FLOW,
|
marci@762
|
92 |
PRE_FLOW,
|
marci@762
|
93 |
NO_FLOW
|
marci@762
|
94 |
};
|
marci@762
|
95 |
|
marci@762
|
96 |
enum StatusEnum {
|
marci@762
|
97 |
AFTER_NOTHING,
|
marci@762
|
98 |
AFTER_AUGMENTING,
|
marci@762
|
99 |
AFTER_FAST_AUGMENTING,
|
marci@762
|
100 |
AFTER_PRE_FLOW_PHASE_1,
|
marci@762
|
101 |
AFTER_PRE_FLOW_PHASE_2
|
marci@762
|
102 |
};
|
marci@762
|
103 |
|
marci@762
|
104 |
/// Don not needle this flag only if necessary.
|
marci@762
|
105 |
StatusEnum status;
|
marci@762
|
106 |
int number_of_augmentations;
|
marci@762
|
107 |
|
marci@762
|
108 |
|
marci@762
|
109 |
template<typename IntMap>
|
marci@762
|
110 |
class TrickyReachedMap {
|
marci@762
|
111 |
protected:
|
marci@762
|
112 |
IntMap* map;
|
marci@762
|
113 |
int* number_of_augmentations;
|
marci@762
|
114 |
public:
|
marci@944
|
115 |
typedef Node KeyType;
|
marci@944
|
116 |
typedef bool ValueType;
|
marci@762
|
117 |
TrickyReachedMap(IntMap& _map, int& _number_of_augmentations) :
|
marci@762
|
118 |
map(&_map), number_of_augmentations(&_number_of_augmentations) { }
|
marci@762
|
119 |
void set(const Node& n, bool b) {
|
marci@762
|
120 |
if (b)
|
marci@762
|
121 |
map->set(n, *number_of_augmentations);
|
marci@762
|
122 |
else
|
marci@762
|
123 |
map->set(n, *number_of_augmentations-1);
|
marci@762
|
124 |
}
|
marci@762
|
125 |
bool operator[](const Node& n) const {
|
marci@762
|
126 |
return (*map)[n]==*number_of_augmentations;
|
marci@762
|
127 |
}
|
marci@762
|
128 |
};
|
marci@762
|
129 |
|
marci@762
|
130 |
AugmentingFlow(const Graph& _G, Node _s, Node _t, const CapMap& _capacity,
|
marci@762
|
131 |
FlowMap& _flow) :
|
marci@762
|
132 |
g(&_G), s(_s), t(_t), capacity(&_capacity),
|
marci@762
|
133 |
flow(&_flow), //n(_G.nodeNum()),
|
marci@762
|
134 |
level(_G), //excess(_G,0),
|
marci@762
|
135 |
status(AFTER_NOTHING), number_of_augmentations(0) { }
|
marci@762
|
136 |
|
marci@762
|
137 |
/// Starting from a flow, this method searches for an augmenting path
|
marci@762
|
138 |
/// according to the Edmonds-Karp algorithm
|
marci@762
|
139 |
/// and augments the flow on if any.
|
marci@762
|
140 |
/// The return value shows if the augmentation was succesful.
|
marci@762
|
141 |
bool augmentOnShortestPath();
|
marci@762
|
142 |
bool augmentOnShortestPath2();
|
marci@762
|
143 |
|
marci@762
|
144 |
/// Starting from a flow, this method searches for an augmenting blocking
|
marci@762
|
145 |
/// flow according to Dinits' algorithm and augments the flow on if any.
|
marci@762
|
146 |
/// The blocking flow is computed in a physically constructed
|
marci@762
|
147 |
/// residual graph of type \c Mutablegraph.
|
marci@762
|
148 |
/// The return value show sif the augmentation was succesful.
|
marci@762
|
149 |
template<typename MutableGraph> bool augmentOnBlockingFlow();
|
marci@762
|
150 |
|
marci@762
|
151 |
/// The same as \c augmentOnBlockingFlow<MutableGraph> but the
|
marci@762
|
152 |
/// residual graph is not constructed physically.
|
marci@762
|
153 |
/// The return value shows if the augmentation was succesful.
|
marci@762
|
154 |
bool augmentOnBlockingFlow2();
|
marci@762
|
155 |
|
marci@762
|
156 |
template<typename _CutMap>
|
marci@762
|
157 |
void actMinCut(_CutMap& M) const {
|
marci@762
|
158 |
NodeIt v;
|
marci@762
|
159 |
switch (status) {
|
marci@762
|
160 |
case AFTER_PRE_FLOW_PHASE_1:
|
marci@762
|
161 |
// std::cout << "AFTER_PRE_FLOW_PHASE_1" << std::endl;
|
marci@762
|
162 |
// for(g->first(v); g->valid(v); g->next(v)) {
|
marci@762
|
163 |
// if (level[v] < n) {
|
marci@762
|
164 |
// M.set(v, false);
|
marci@762
|
165 |
// } else {
|
marci@762
|
166 |
// M.set(v, true);
|
marci@762
|
167 |
// }
|
marci@762
|
168 |
// }
|
marci@762
|
169 |
break;
|
marci@762
|
170 |
case AFTER_PRE_FLOW_PHASE_2:
|
marci@762
|
171 |
// std::cout << "AFTER_PRE_FLOW_PHASE_2" << std::endl;
|
marci@762
|
172 |
break;
|
marci@762
|
173 |
case AFTER_NOTHING:
|
marci@762
|
174 |
// std::cout << "AFTER_NOTHING" << std::endl;
|
marci@762
|
175 |
minMinCut(M);
|
marci@762
|
176 |
break;
|
marci@762
|
177 |
case AFTER_AUGMENTING:
|
marci@762
|
178 |
// std::cout << "AFTER_AUGMENTING" << std::endl;
|
marci@775
|
179 |
for(g->first(v); v!=INVALID; ++v) {
|
marci@762
|
180 |
if (level[v]) {
|
marci@762
|
181 |
M.set(v, true);
|
marci@762
|
182 |
} else {
|
marci@762
|
183 |
M.set(v, false);
|
marci@762
|
184 |
}
|
marci@762
|
185 |
}
|
marci@762
|
186 |
break;
|
marci@762
|
187 |
case AFTER_FAST_AUGMENTING:
|
marci@762
|
188 |
// std::cout << "AFTER_FAST_AUGMENTING" << std::endl;
|
marci@775
|
189 |
for(g->first(v); v!=INVALID; ++v) {
|
marci@762
|
190 |
if (level[v]==number_of_augmentations) {
|
marci@762
|
191 |
M.set(v, true);
|
marci@762
|
192 |
} else {
|
marci@762
|
193 |
M.set(v, false);
|
marci@762
|
194 |
}
|
marci@762
|
195 |
}
|
marci@762
|
196 |
break;
|
marci@762
|
197 |
}
|
marci@762
|
198 |
}
|
marci@762
|
199 |
|
marci@762
|
200 |
template<typename _CutMap>
|
marci@762
|
201 |
void minMinCut(_CutMap& M) const {
|
marci@762
|
202 |
std::queue<Node> queue;
|
marci@762
|
203 |
|
marci@762
|
204 |
M.set(s,true);
|
marci@762
|
205 |
queue.push(s);
|
marci@762
|
206 |
|
marci@762
|
207 |
while (!queue.empty()) {
|
marci@762
|
208 |
Node w=queue.front();
|
marci@762
|
209 |
queue.pop();
|
marci@762
|
210 |
|
marci@762
|
211 |
OutEdgeIt e;
|
marci@775
|
212 |
for(g->first(e,w) ; e!=INVALID; ++e) {
|
marci@762
|
213 |
Node v=g->head(e);
|
marci@762
|
214 |
if (!M[v] && (*flow)[e] < (*capacity)[e] ) {
|
marci@762
|
215 |
queue.push(v);
|
marci@762
|
216 |
M.set(v, true);
|
marci@762
|
217 |
}
|
marci@762
|
218 |
}
|
marci@762
|
219 |
|
marci@762
|
220 |
InEdgeIt f;
|
marci@775
|
221 |
for(g->first(f,w) ; f!=INVALID; ++f) {
|
marci@762
|
222 |
Node v=g->tail(f);
|
marci@762
|
223 |
if (!M[v] && (*flow)[f] > 0 ) {
|
marci@762
|
224 |
queue.push(v);
|
marci@762
|
225 |
M.set(v, true);
|
marci@762
|
226 |
}
|
marci@762
|
227 |
}
|
marci@762
|
228 |
}
|
marci@762
|
229 |
}
|
marci@762
|
230 |
|
marci@762
|
231 |
template<typename _CutMap>
|
marci@762
|
232 |
void minMinCut2(_CutMap& M) const {
|
marci@762
|
233 |
ResGW res_graph(*g, *capacity, *flow);
|
marci@762
|
234 |
BfsIterator<ResGW, _CutMap> bfs(res_graph, M);
|
marci@762
|
235 |
bfs.pushAndSetReached(s);
|
marci@762
|
236 |
while (!bfs.finished()) ++bfs;
|
marci@762
|
237 |
}
|
marci@762
|
238 |
|
marci@762
|
239 |
Num flowValue() const {
|
marci@762
|
240 |
Num a=0;
|
marci@777
|
241 |
for (InEdgeIt e(*g, t); e!=INVALID; ++e) a+=(*flow)[e];
|
marci@777
|
242 |
for (OutEdgeIt e(*g, t); e!=INVALID; ++e) a-=(*flow)[e];
|
marci@762
|
243 |
return a;
|
marci@762
|
244 |
//marci figyu: excess[t] epp ezt adja preflow 1. fazisa utan
|
marci@762
|
245 |
}
|
marci@762
|
246 |
|
marci@762
|
247 |
};
|
marci@762
|
248 |
|
marci@762
|
249 |
|
marci@762
|
250 |
|
marci@762
|
251 |
template <typename Graph, typename Num, typename CapMap, typename FlowMap>
|
marci@762
|
252 |
bool AugmentingFlow<Graph, Num, CapMap, FlowMap>::augmentOnShortestPath()
|
marci@762
|
253 |
{
|
marci@762
|
254 |
ResGW res_graph(*g, *capacity, *flow);
|
marci@888
|
255 |
typename ResGW::ResCap res_cap(res_graph);
|
marci@888
|
256 |
|
marci@762
|
257 |
bool _augment=false;
|
marci@762
|
258 |
|
marci@762
|
259 |
//ReachedMap level(res_graph);
|
marci@777
|
260 |
for (typename Graph::NodeIt n(*g); n!=INVALID; ++n) level.set(n, 0);
|
marci@762
|
261 |
BfsIterator<ResGW, ReachedMap> bfs(res_graph, level);
|
marci@762
|
262 |
bfs.pushAndSetReached(s);
|
marci@762
|
263 |
|
marci@762
|
264 |
typename ResGW::template NodeMap<ResGWEdge> pred(res_graph);
|
marci@762
|
265 |
pred.set(s, INVALID);
|
marci@762
|
266 |
|
marci@762
|
267 |
typename ResGW::template NodeMap<Num> free(res_graph);
|
marci@762
|
268 |
|
marci@762
|
269 |
//searching for augmenting path
|
marci@762
|
270 |
while ( !bfs.finished() ) {
|
marci@777
|
271 |
ResGWEdge e=bfs;
|
marci@775
|
272 |
if (e!=INVALID && bfs.isBNodeNewlyReached()) {
|
marci@762
|
273 |
Node v=res_graph.tail(e);
|
marci@762
|
274 |
Node w=res_graph.head(e);
|
marci@762
|
275 |
pred.set(w, e);
|
marci@775
|
276 |
if (pred[v]!=INVALID) {
|
marci@888
|
277 |
free.set(w, std::min(free[v], res_cap[e]));
|
marci@762
|
278 |
} else {
|
marci@888
|
279 |
free.set(w, res_cap[e]);
|
marci@762
|
280 |
}
|
marci@762
|
281 |
if (res_graph.head(e)==t) { _augment=true; break; }
|
marci@762
|
282 |
}
|
marci@762
|
283 |
|
marci@762
|
284 |
++bfs;
|
marci@762
|
285 |
} //end of searching augmenting path
|
marci@762
|
286 |
|
marci@762
|
287 |
if (_augment) {
|
marci@762
|
288 |
Node n=t;
|
marci@762
|
289 |
Num augment_value=free[t];
|
marci@775
|
290 |
while (pred[n]!=INVALID) {
|
marci@762
|
291 |
ResGWEdge e=pred[n];
|
marci@762
|
292 |
res_graph.augment(e, augment_value);
|
marci@762
|
293 |
n=res_graph.tail(e);
|
marci@762
|
294 |
}
|
marci@762
|
295 |
}
|
marci@762
|
296 |
|
marci@762
|
297 |
status=AFTER_AUGMENTING;
|
marci@762
|
298 |
return _augment;
|
marci@762
|
299 |
}
|
marci@762
|
300 |
|
marci@762
|
301 |
template <typename Graph, typename Num, typename CapMap, typename FlowMap>
|
marci@762
|
302 |
bool AugmentingFlow<Graph, Num, CapMap, FlowMap>::augmentOnShortestPath2()
|
marci@762
|
303 |
{
|
marci@762
|
304 |
ResGW res_graph(*g, *capacity, *flow);
|
marci@888
|
305 |
typename ResGW::ResCap res_cap(res_graph);
|
marci@888
|
306 |
|
marci@762
|
307 |
bool _augment=false;
|
marci@762
|
308 |
|
marci@762
|
309 |
if (status!=AFTER_FAST_AUGMENTING) {
|
marci@777
|
310 |
for (typename Graph::NodeIt n(*g); n!=INVALID; ++n) level.set(n, 0);
|
marci@762
|
311 |
number_of_augmentations=1;
|
marci@762
|
312 |
} else {
|
marci@762
|
313 |
++number_of_augmentations;
|
marci@762
|
314 |
}
|
marci@762
|
315 |
TrickyReachedMap<ReachedMap>
|
marci@762
|
316 |
tricky_reached_map(level, number_of_augmentations);
|
marci@762
|
317 |
//ReachedMap level(res_graph);
|
marci@762
|
318 |
// FOR_EACH_LOC(typename Graph::NodeIt, e, *g) level.set(e, 0);
|
marci@762
|
319 |
BfsIterator<ResGW, TrickyReachedMap<ReachedMap> >
|
marci@762
|
320 |
bfs(res_graph, tricky_reached_map);
|
marci@762
|
321 |
bfs.pushAndSetReached(s);
|
marci@762
|
322 |
|
marci@762
|
323 |
typename ResGW::template NodeMap<ResGWEdge> pred(res_graph);
|
marci@762
|
324 |
pred.set(s, INVALID);
|
marci@762
|
325 |
|
marci@762
|
326 |
typename ResGW::template NodeMap<Num> free(res_graph);
|
marci@762
|
327 |
|
marci@762
|
328 |
//searching for augmenting path
|
marci@762
|
329 |
while ( !bfs.finished() ) {
|
marci@777
|
330 |
ResGWEdge e=bfs;
|
marci@775
|
331 |
if (e!=INVALID && bfs.isBNodeNewlyReached()) {
|
marci@762
|
332 |
Node v=res_graph.tail(e);
|
marci@762
|
333 |
Node w=res_graph.head(e);
|
marci@762
|
334 |
pred.set(w, e);
|
marci@775
|
335 |
if (pred[v]!=INVALID) {
|
marci@888
|
336 |
free.set(w, std::min(free[v], res_cap[e]));
|
marci@762
|
337 |
} else {
|
marci@888
|
338 |
free.set(w, res_cap[e]);
|
marci@762
|
339 |
}
|
marci@762
|
340 |
if (res_graph.head(e)==t) { _augment=true; break; }
|
marci@762
|
341 |
}
|
marci@762
|
342 |
|
marci@762
|
343 |
++bfs;
|
marci@762
|
344 |
} //end of searching augmenting path
|
marci@762
|
345 |
|
marci@762
|
346 |
if (_augment) {
|
marci@762
|
347 |
Node n=t;
|
marci@762
|
348 |
Num augment_value=free[t];
|
marci@775
|
349 |
while (pred[n]!=INVALID) {
|
marci@762
|
350 |
ResGWEdge e=pred[n];
|
marci@762
|
351 |
res_graph.augment(e, augment_value);
|
marci@762
|
352 |
n=res_graph.tail(e);
|
marci@762
|
353 |
}
|
marci@762
|
354 |
}
|
marci@762
|
355 |
|
marci@762
|
356 |
status=AFTER_FAST_AUGMENTING;
|
marci@762
|
357 |
return _augment;
|
marci@762
|
358 |
}
|
marci@762
|
359 |
|
marci@762
|
360 |
|
marci@762
|
361 |
template <typename Graph, typename Num, typename CapMap, typename FlowMap>
|
marci@762
|
362 |
template<typename MutableGraph>
|
marci@762
|
363 |
bool AugmentingFlow<Graph, Num, CapMap, FlowMap>::augmentOnBlockingFlow()
|
marci@762
|
364 |
{
|
marci@762
|
365 |
typedef MutableGraph MG;
|
marci@762
|
366 |
bool _augment=false;
|
marci@762
|
367 |
|
marci@762
|
368 |
ResGW res_graph(*g, *capacity, *flow);
|
marci@888
|
369 |
typename ResGW::ResCap res_cap(res_graph);
|
marci@762
|
370 |
|
marci@762
|
371 |
//bfs for distances on the residual graph
|
marci@762
|
372 |
//ReachedMap level(res_graph);
|
marci@777
|
373 |
for (typename Graph::NodeIt n(*g); n!=INVALID; ++n) level.set(n, 0);
|
marci@762
|
374 |
BfsIterator<ResGW, ReachedMap> bfs(res_graph, level);
|
marci@762
|
375 |
bfs.pushAndSetReached(s);
|
marci@762
|
376 |
typename ResGW::template NodeMap<int>
|
marci@762
|
377 |
dist(res_graph); //filled up with 0's
|
marci@762
|
378 |
|
marci@762
|
379 |
//F will contain the physical copy of the residual graph
|
marci@762
|
380 |
//with the set of edges which are on shortest paths
|
marci@762
|
381 |
MG F;
|
marci@762
|
382 |
typename ResGW::template NodeMap<typename MG::Node>
|
marci@762
|
383 |
res_graph_to_F(res_graph);
|
marci@762
|
384 |
{
|
marci@762
|
385 |
typename ResGW::NodeIt n;
|
marci@862
|
386 |
for(res_graph.first(n); n!=INVALID; ++n)
|
marci@762
|
387 |
res_graph_to_F.set(n, F.addNode());
|
marci@762
|
388 |
}
|
marci@762
|
389 |
|
marci@762
|
390 |
typename MG::Node sF=res_graph_to_F[s];
|
marci@762
|
391 |
typename MG::Node tF=res_graph_to_F[t];
|
marci@762
|
392 |
typename MG::template EdgeMap<ResGWEdge> original_edge(F);
|
marci@762
|
393 |
typename MG::template EdgeMap<Num> residual_capacity(F);
|
marci@762
|
394 |
|
marci@762
|
395 |
while ( !bfs.finished() ) {
|
marci@777
|
396 |
ResGWEdge e=bfs;
|
marci@775
|
397 |
if (e!=INVALID) {
|
marci@762
|
398 |
if (bfs.isBNodeNewlyReached()) {
|
marci@762
|
399 |
dist.set(res_graph.head(e), dist[res_graph.tail(e)]+1);
|
marci@762
|
400 |
typename MG::Edge f=F.addEdge(res_graph_to_F[res_graph.tail(e)],
|
marci@762
|
401 |
res_graph_to_F[res_graph.head(e)]);
|
marci@854
|
402 |
//original_edge.update();
|
marci@762
|
403 |
original_edge.set(f, e);
|
marci@854
|
404 |
//residual_capacity.update();
|
marci@888
|
405 |
residual_capacity.set(f, res_cap[e]);
|
marci@762
|
406 |
} else {
|
marci@762
|
407 |
if (dist[res_graph.head(e)]==(dist[res_graph.tail(e)]+1)) {
|
marci@762
|
408 |
typename MG::Edge f=F.addEdge(res_graph_to_F[res_graph.tail(e)],
|
marci@762
|
409 |
res_graph_to_F[res_graph.head(e)]);
|
marci@854
|
410 |
//original_edge.update();
|
marci@762
|
411 |
original_edge.set(f, e);
|
marci@854
|
412 |
//residual_capacity.update();
|
marci@888
|
413 |
residual_capacity.set(f, res_cap[e]);
|
marci@762
|
414 |
}
|
marci@762
|
415 |
}
|
marci@762
|
416 |
}
|
marci@762
|
417 |
++bfs;
|
marci@762
|
418 |
} //computing distances from s in the residual graph
|
marci@762
|
419 |
|
marci@762
|
420 |
bool __augment=true;
|
marci@762
|
421 |
|
marci@762
|
422 |
while (__augment) {
|
marci@762
|
423 |
__augment=false;
|
marci@762
|
424 |
//computing blocking flow with dfs
|
marci@762
|
425 |
DfsIterator< MG, typename MG::template NodeMap<bool> > dfs(F);
|
marci@762
|
426 |
typename MG::template NodeMap<typename MG::Edge> pred(F);
|
marci@762
|
427 |
pred.set(sF, INVALID);
|
marci@762
|
428 |
//invalid iterators for sources
|
marci@762
|
429 |
|
marci@762
|
430 |
typename MG::template NodeMap<Num> free(F);
|
marci@762
|
431 |
|
marci@762
|
432 |
dfs.pushAndSetReached(sF);
|
marci@762
|
433 |
while (!dfs.finished()) {
|
marci@762
|
434 |
++dfs;
|
marci@854
|
435 |
if (typename MG::Edge(dfs)!=INVALID) {
|
marci@762
|
436 |
if (dfs.isBNodeNewlyReached()) {
|
marci@777
|
437 |
typename MG::Node v=F.tail(dfs);
|
marci@777
|
438 |
typename MG::Node w=F.head(dfs);
|
marci@762
|
439 |
pred.set(w, dfs);
|
marci@775
|
440 |
if (pred[v]!=INVALID) {
|
marci@762
|
441 |
free.set(w, std::min(free[v], residual_capacity[dfs]));
|
marci@762
|
442 |
} else {
|
marci@762
|
443 |
free.set(w, residual_capacity[dfs]);
|
marci@762
|
444 |
}
|
marci@762
|
445 |
if (w==tF) {
|
marci@762
|
446 |
__augment=true;
|
marci@762
|
447 |
_augment=true;
|
marci@762
|
448 |
break;
|
marci@762
|
449 |
}
|
marci@762
|
450 |
|
marci@762
|
451 |
} else {
|
marci@854
|
452 |
F.erase(typename MG::Edge(dfs));
|
marci@762
|
453 |
}
|
marci@762
|
454 |
}
|
marci@762
|
455 |
}
|
marci@762
|
456 |
|
marci@762
|
457 |
if (__augment) {
|
marci@762
|
458 |
typename MG::Node n=tF;
|
marci@762
|
459 |
Num augment_value=free[tF];
|
marci@775
|
460 |
while (pred[n]!=INVALID) {
|
marci@762
|
461 |
typename MG::Edge e=pred[n];
|
marci@762
|
462 |
res_graph.augment(original_edge[e], augment_value);
|
marci@762
|
463 |
n=F.tail(e);
|
marci@762
|
464 |
if (residual_capacity[e]==augment_value)
|
marci@762
|
465 |
F.erase(e);
|
marci@762
|
466 |
else
|
marci@762
|
467 |
residual_capacity.set(e, residual_capacity[e]-augment_value);
|
marci@762
|
468 |
}
|
marci@762
|
469 |
}
|
marci@762
|
470 |
|
marci@762
|
471 |
}
|
marci@762
|
472 |
|
marci@762
|
473 |
status=AFTER_AUGMENTING;
|
marci@762
|
474 |
return _augment;
|
marci@762
|
475 |
}
|
marci@762
|
476 |
|
marci@862
|
477 |
/// Blocking flow augmentation without constructing the layered
|
marci@862
|
478 |
/// graph physically in which the blocking flow is computed.
|
marci@762
|
479 |
template <typename Graph, typename Num, typename CapMap, typename FlowMap>
|
marci@762
|
480 |
bool AugmentingFlow<Graph, Num, CapMap, FlowMap>::augmentOnBlockingFlow2()
|
marci@762
|
481 |
{
|
marci@762
|
482 |
bool _augment=false;
|
marci@762
|
483 |
|
marci@762
|
484 |
ResGW res_graph(*g, *capacity, *flow);
|
marci@888
|
485 |
typename ResGW::ResCap res_cap(res_graph);
|
marci@762
|
486 |
|
marci@862
|
487 |
//Potential map, for distances from s
|
marci@862
|
488 |
typename ResGW::template NodeMap<int> potential(res_graph, 0);
|
marci@862
|
489 |
typedef ConstMap<typename ResGW::Edge, int> Const1Map;
|
marci@862
|
490 |
Const1Map const_1_map(1);
|
marci@862
|
491 |
TightEdgeFilterMap<ResGW, typename ResGW::template NodeMap<int>,
|
marci@862
|
492 |
Const1Map> tight_edge_filter(res_graph, potential, const_1_map);
|
marci@862
|
493 |
|
marci@777
|
494 |
for (typename Graph::NodeIt n(*g); n!=INVALID; ++n) level.set(n, 0);
|
marci@762
|
495 |
BfsIterator<ResGW, ReachedMap> bfs(res_graph, level);
|
marci@862
|
496 |
bfs.pushAndSetReached(s);
|
marci@762
|
497 |
|
marci@862
|
498 |
//computing distances from s in the residual graph
|
marci@762
|
499 |
while ( !bfs.finished() ) {
|
marci@777
|
500 |
ResGWEdge e=bfs;
|
marci@862
|
501 |
if (e!=INVALID && bfs.isBNodeNewlyReached())
|
marci@862
|
502 |
potential.set(res_graph.head(e), potential[res_graph.tail(e)]+1);
|
marci@762
|
503 |
++bfs;
|
marci@862
|
504 |
}
|
marci@762
|
505 |
|
marci@862
|
506 |
//Subgraph containing the edges on some shortest paths
|
marci@862
|
507 |
//(i.e. tight edges)
|
marci@762
|
508 |
ConstMap<typename ResGW::Node, bool> true_map(true);
|
marci@762
|
509 |
typedef SubGraphWrapper<ResGW, ConstMap<typename ResGW::Node, bool>,
|
marci@862
|
510 |
TightEdgeFilterMap<ResGW, typename ResGW::template NodeMap<int>,
|
marci@862
|
511 |
Const1Map> > FilterResGW;
|
marci@862
|
512 |
FilterResGW filter_res_graph(res_graph, true_map, tight_edge_filter);
|
marci@762
|
513 |
|
marci@762
|
514 |
//Subgraph, which is able to delete edges which are already
|
marci@762
|
515 |
//met by the dfs
|
marci@777
|
516 |
typename FilterResGW::template NodeMap<typename FilterResGW::Edge>
|
marci@762
|
517 |
first_out_edges(filter_res_graph);
|
marci@862
|
518 |
for (typename FilterResGW::NodeIt v(filter_res_graph); v!=INVALID; ++v)
|
marci@862
|
519 |
first_out_edges.set
|
marci@862
|
520 |
(v, typename FilterResGW::OutEdgeIt(filter_res_graph, v));
|
marci@862
|
521 |
|
marci@762
|
522 |
typedef ErasingFirstGraphWrapper<FilterResGW, typename FilterResGW::
|
marci@777
|
523 |
template NodeMap<typename FilterResGW::Edge> > ErasingResGW;
|
marci@762
|
524 |
ErasingResGW erasing_res_graph(filter_res_graph, first_out_edges);
|
marci@762
|
525 |
|
marci@762
|
526 |
bool __augment=true;
|
marci@762
|
527 |
|
marci@762
|
528 |
while (__augment) {
|
marci@762
|
529 |
|
marci@762
|
530 |
__augment=false;
|
marci@762
|
531 |
//computing blocking flow with dfs
|
marci@762
|
532 |
DfsIterator< ErasingResGW,
|
marci@762
|
533 |
typename ErasingResGW::template NodeMap<bool> >
|
marci@762
|
534 |
dfs(erasing_res_graph);
|
marci@762
|
535 |
typename ErasingResGW::
|
marci@777
|
536 |
template NodeMap<typename ErasingResGW::Edge> pred(erasing_res_graph);
|
marci@762
|
537 |
pred.set(s, INVALID);
|
marci@762
|
538 |
//invalid iterators for sources
|
marci@762
|
539 |
|
marci@762
|
540 |
typename ErasingResGW::template NodeMap<Num>
|
marci@762
|
541 |
free1(erasing_res_graph);
|
marci@762
|
542 |
|
marci@762
|
543 |
dfs.pushAndSetReached
|
alpar@921
|
544 |
/// \bug lemon 0.2
|
marci@762
|
545 |
(typename ErasingResGW::Node
|
marci@762
|
546 |
(typename FilterResGW::Node
|
marci@762
|
547 |
(typename ResGW::Node(s)
|
marci@762
|
548 |
)
|
marci@762
|
549 |
)
|
marci@762
|
550 |
);
|
marci@777
|
551 |
|
marci@762
|
552 |
while (!dfs.finished()) {
|
marci@762
|
553 |
++dfs;
|
marci@862
|
554 |
if (typename ErasingResGW::Edge(dfs)!=INVALID) {
|
marci@862
|
555 |
if (dfs.isBNodeNewlyReached()) {
|
marci@862
|
556 |
|
marci@862
|
557 |
typename ErasingResGW::Node v=erasing_res_graph.tail(dfs);
|
marci@862
|
558 |
typename ErasingResGW::Node w=erasing_res_graph.head(dfs);
|
marci@762
|
559 |
|
marci@862
|
560 |
pred.set(w, typename ErasingResGW::Edge(dfs));
|
marci@862
|
561 |
if (pred[v]!=INVALID) {
|
marci@862
|
562 |
free1.set
|
marci@888
|
563 |
(w, std::min(free1[v], res_cap
|
marci@888
|
564 |
[typename ErasingResGW::Edge(dfs)]));
|
marci@862
|
565 |
} else {
|
marci@862
|
566 |
free1.set
|
marci@888
|
567 |
(w, res_cap
|
marci@888
|
568 |
[typename ErasingResGW::Edge(dfs)]);
|
marci@862
|
569 |
}
|
marci@762
|
570 |
|
marci@862
|
571 |
if (w==t) {
|
marci@862
|
572 |
__augment=true;
|
marci@862
|
573 |
_augment=true;
|
marci@862
|
574 |
break;
|
marci@762
|
575 |
}
|
marci@862
|
576 |
} else {
|
marci@862
|
577 |
erasing_res_graph.erase(dfs);
|
marci@762
|
578 |
}
|
marci@862
|
579 |
}
|
marci@762
|
580 |
}
|
marci@762
|
581 |
|
marci@762
|
582 |
if (__augment) {
|
marci@762
|
583 |
typename ErasingResGW::Node
|
marci@762
|
584 |
n=typename FilterResGW::Node(typename ResGW::Node(t));
|
marci@762
|
585 |
Num augment_value=free1[n];
|
marci@777
|
586 |
while (pred[n]!=INVALID) {
|
marci@777
|
587 |
typename ErasingResGW::Edge e=pred[n];
|
marci@762
|
588 |
res_graph.augment(e, augment_value);
|
marci@762
|
589 |
n=erasing_res_graph.tail(e);
|
marci@888
|
590 |
if (res_cap[e]==0)
|
marci@762
|
591 |
erasing_res_graph.erase(e);
|
marci@762
|
592 |
}
|
marci@762
|
593 |
}
|
marci@762
|
594 |
|
marci@762
|
595 |
} //while (__augment)
|
marci@762
|
596 |
|
marci@762
|
597 |
status=AFTER_AUGMENTING;
|
marci@762
|
598 |
return _augment;
|
marci@762
|
599 |
}
|
marci@762
|
600 |
|
marci@762
|
601 |
|
alpar@921
|
602 |
} //namespace lemon
|
marci@762
|
603 |
|
alpar@921
|
604 |
#endif //LEMON_AUGMENTING_FLOW_H
|
marci@762
|
605 |
|
marci@762
|
606 |
|