src/work/jacint/preflow_push_hl.h
author marci
Tue, 17 Feb 2004 11:24:21 +0000
changeset 87 46705346edd4
parent 84 56e879edcca6
child 88 93bb934b0794
permissions -rw-r--r--
mostmar pontosabb erteket ad
     1 // -*- C++ -*-
     2 /*
     3 preflow_push_hl.h
     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(EdgeIt e) : for a fixed maximum flow x it returns x(e) 
    17 
    18 Graph::EdgeMap<T> allflow() : returns the fixed maximum flow x
    19 
    20 Graph::NodeMap<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.h>
    33 
    34 namespace marci {
    35 
    36   template <typename Graph, typename T>
    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     
    45     Graph& G;
    46     NodeIt s;
    47     NodeIt t;
    48     typename Graph::EdgeMap<T> flow;
    49     typename Graph::EdgeMap<T> capacity; 
    50     T value;
    51     typename Graph::NodeMap<bool> mincutvector;
    52 
    53   public:
    54 
    55     preflow_push_hl(Graph& _G, NodeIt _s, NodeIt _t, 
    56 		    typename Graph::EdgeMap<T>& _capacity) :
    57       G(_G), s(_s), t(_t), flow(_G, 0), capacity(_capacity), 
    58       mincutvector(_G, true) { }
    59 
    60 
    61     /*
    62       The run() function runs the highest label preflow-push, 
    63       running time: O(n^2\sqrt(m))
    64     */
    65     void run() {
    66  
    67       typename Graph::NodeMap<int> level(G);      
    68       typename Graph::NodeMap<T> excess(G); 
    69 
    70       int n=G.nodeNum(); 
    71       int b=n-2; 
    72       /*
    73 	b is a bound on the highest level of an active node. 
    74 	In the beginning it is at most n-2.
    75       */
    76 
    77       std::vector<int> numb(n);     //The number of nodes on level i < n.
    78       std::vector<std::stack<NodeIt> > stack(2*n-1);    
    79       //Stack of the active nodes in level i.
    80 
    81 
    82       /*Reverse_bfs from t, to find the starting level.*/
    83       reverse_bfs<Graph> bfs(G, t);
    84       bfs.run();
    85       for(EachNodeIt v=G.template first<EachNodeIt>(); v.valid(); ++v) 
    86 	{
    87 	  int dist=bfs.dist(v);
    88 	  level.set(v, dist);
    89 	  ++numb[dist];
    90 	}
    91 
    92       level.set(s,n);
    93 
    94 
    95       /* Starting flow. It is everywhere 0 at the moment. */     
    96       for(OutEdgeIt e=G.template first<OutEdgeIt>(s); e.valid(); ++e) 
    97 	{
    98 	  if ( capacity.get(e) > 0 ) {
    99 	    NodeIt w=G.head(e);
   100 	    if ( w!=s ) {	  
   101 	      if ( excess.get(w) == 0 && w!=t ) stack[level.get(w)].push(w); 
   102 	      flow.set(e, capacity.get(e)); 
   103 	      excess.set(w, excess.get(w)+capacity.get(e));
   104 	    }
   105 	  }
   106 	}
   107 
   108       /* 
   109 	 End of preprocessing 
   110       */
   111 
   112 
   113 
   114       /*
   115 	Push/relabel on the highest level active nodes.
   116       */
   117 	
   118       /*While there exists an active node.*/
   119       while (b) { 
   120 
   121 	/*We decrease the bound if there is no active node of level b.*/
   122 	if (stack[b].empty()) {
   123 	  --b;
   124 	} else {
   125 
   126 	  NodeIt w=stack[b].top();        //w is a highest label active node.
   127 	  stack[b].pop();           
   128 	
   129 	  int newlevel=2*n-2;             //In newlevel we bound the next level of w.
   130 	
   131 	  for(OutEdgeIt e=G.template first<OutEdgeIt>(w); e.valid(); ++e) {
   132 	    
   133 	    if ( flow.get(e) < capacity.get(e) ) {              
   134 	      /*e is an edge of the residual graph */
   135 
   136 	      NodeIt v=G.head(e);               /*e is the edge wv.*/
   137 
   138 	      if( level.get(w) == level.get(v)+1 ) {      
   139 		/*Push is allowed now*/
   140 
   141 		if ( excess.get(v)==0 && v != s && v !=t ) stack[level.get(v)].push(v); 
   142 		/*v becomes active.*/
   143 
   144 		if ( capacity.get(e)-flow.get(e) > excess.get(w) ) {       
   145 		  /*A nonsaturating push.*/
   146 		  
   147 		  flow.set(e, flow.get(e)+excess.get(w));
   148 		  excess.set(v, excess.get(v)+excess.get(w));
   149 		  excess.set(w,0);
   150 		  break; 
   151 
   152 		} else { 
   153 		  /*A saturating push.*/
   154 
   155 		  excess.set(v, excess.get(v)+capacity.get(e)-flow.get(e));
   156 		  excess.set(w, excess.get(w)-capacity.get(e)+flow.get(e));
   157 		  flow.set(e, capacity.get(e));
   158 		  if ( excess.get(w)==0 ) break;
   159 		  /*If w is not active any more, then we go on to the next node.*/
   160 		  
   161 		}
   162 	      } else {
   163 		newlevel = newlevel < level.get(v) ? newlevel : level.get(v);
   164 	      }
   165 	    
   166 	    } //if the out edge wv is in the res graph 
   167 	 
   168 	  } //for out edges wv 
   169 	  
   170 
   171 	  if ( excess.get(w) > 0 ) {	
   172 	    
   173 	    for( InEdgeIt e=G.template first<InEdgeIt>(w); e.valid(); ++e) {
   174 	      NodeIt v=G.tail(e);  /*e is the edge vw.*/
   175 
   176 	      if( flow.get(e) > 0 ) {             
   177 		/*e is an edge of the residual graph */
   178 
   179 		if( level.get(w)==level.get(v)+1 ) {  
   180 		  /*Push is allowed now*/
   181 		
   182 		  if ( excess.get(v)==0 && v != s && v !=t) stack[level.get(v)].push(v); 
   183 		  /*v becomes active.*/
   184 
   185 		  if ( flow.get(e) > excess.get(w) ) { 
   186 		    /*A nonsaturating push.*/
   187 		  
   188 		    flow.set(e, flow.get(e)-excess.get(w));
   189 		    excess.set(v, excess.get(v)+excess.get(w));
   190 		    excess.set(w,0);
   191 		    break; 
   192 		  } else {                                               
   193 		    /*A saturating push.*/
   194 		    
   195 		    excess.set(v, excess.get(v)+flow.get(e));
   196 		    excess.set(w, excess.get(w)-flow.get(e));
   197 		    flow.set(e,0);
   198 		    if ( excess.get(w)==0 ) break;
   199 		  }  
   200 		} else {
   201 		  newlevel = newlevel < level.get(v) ? newlevel : level.get(v);
   202 		}
   203 		
   204 	      } //if in edge vw is in the res graph 
   205 
   206 	    } //for in edges vw
   207 
   208 	  } // if w still has excess after the out edge for cycle
   209 
   210 
   211 	  /*
   212 	    Relabel
   213 	  */
   214 	  
   215 	  if ( excess.get(w) > 0 ) {
   216 	    
   217 	    int oldlevel=level.get(w);	    
   218 	    level.set(w,++newlevel);
   219 
   220 	    if ( oldlevel < n ) {
   221 	      --numb[oldlevel];
   222 
   223 	      if ( !numb[oldlevel] ) {  //If the level of w gets empty. 
   224 		
   225 		for (EachNodeIt v=G.template first<EachNodeIt>(); v.valid() ; ++v) {
   226 		  if (level.get(v) > oldlevel && level.get(v) < n ) level.set(v,n);  
   227 		}
   228 		for (int i=oldlevel+1 ; i!=n ; ++i) numb[i]=0; 
   229 		if ( newlevel < n ) newlevel=n; 
   230 	      } else { 
   231 		if ( newlevel < n ) ++numb[newlevel]; 
   232 	      }
   233 	    } else { 
   234 	    if ( newlevel < n ) ++numb[newlevel];
   235 	    }
   236 	    
   237 	    stack[newlevel].push(w);
   238 	    b=newlevel;
   239 
   240 	  }
   241 
   242 	} // if stack[b] is nonempty
   243 
   244       } // while(b)
   245 
   246 
   247       value = excess.get(t);
   248       /*Max flow value.*/
   249 
   250 
   251     } //void run()
   252 
   253 
   254 
   255 
   256 
   257     /*
   258       Returns the maximum value of a flow.
   259      */
   260 
   261     T maxflow() {
   262       return value;
   263     }
   264 
   265 
   266 
   267     /*
   268       For the maximum flow x found by the algorithm, it returns the flow value on Edge e, i.e. x(e). 
   269     */
   270 
   271     T flowonEdge(EdgeIt e) {
   272       return flow.get(e);
   273     }
   274 
   275 
   276 
   277     /*
   278       Returns the maximum flow x found by the algorithm.
   279     */
   280 
   281     typename Graph::EdgeMap<T> allflow() {
   282       return flow;
   283     }
   284 
   285 
   286 
   287     /*
   288       Returns a minimum cut by using a reverse bfs from t in the residual graph.
   289     */
   290     
   291     typename Graph::NodeMap<bool> mincut() {
   292     
   293       std::queue<NodeIt> queue;
   294       
   295       mincutvector.set(t,false);      
   296       queue.push(t);
   297 
   298       while (!queue.empty()) {
   299         NodeIt w=queue.front();
   300 	queue.pop();
   301 
   302 	for(InEdgeIt e=G.template first<InEdgeIt>(w) ; e.valid(); ++e) {
   303 	  NodeIt v=G.tail(e);
   304 	  if (mincutvector.get(v) && flow.get(e) < capacity.get(e) ) {
   305 	    queue.push(v);
   306 	    mincutvector.set(v, false);
   307 	  }
   308 	} // for
   309 
   310 	for(OutEdgeIt e=G.template first<OutEdgeIt>(w) ; e.valid(); ++e) {
   311 	  NodeIt v=G.head(e);
   312 	  if (mincutvector.get(v) && flow.get(e) > 0 ) {
   313 	    queue.push(v);
   314 	    mincutvector.set(v, false);
   315 	  }
   316 	} // for
   317 
   318       }
   319 
   320       return mincutvector;
   321     
   322     }
   323   };
   324 }//namespace marci
   325 #endif 
   326 
   327 
   328 
   329