COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/work/jacint/preflow_push_hl.h @ 72:e560867cbe79

Last change on this file since 72:e560867cbe79 was 72:e560867cbe79, checked in by jacint, 17 years ago

modern valtozat

File size: 7.5 KB
Line 
1// -*- C++ -*-
2/*
3preflow_push_hl.hh
4by jacint.
5Runs the highest label variant of the preflow push algorithm with
6running time O(n^2\sqrt(m)).
7
8Member functions:
9
10void run() : runs the algorithm
11
12 The following functions should be used after run() was already run.
13
14T maxflow() : returns the value of a maximum flow
15
16T flowonEdge(Edge_iterator e) : for a fixed maximum flow x it returns x(e)
17
18EdgeMap<graph_type, T> allflow() : returns the fixed maximum flow x
19
20NodeMap<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
34namespace 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
Note: See TracBrowser for help on using the repository browser.