src/work/jacint/preflow_push_max_flow.h
author jacint
Wed, 18 Feb 2004 21:50:45 +0000
changeset 101 d2ac583ed195
parent 85 15362fafaf1a
child 105 a3c73e9b9b2e
permissions -rw-r--r--
another heuristic
jacint@97
     1
// -*- C++ -*-
jacint@78
     2
/*
jacint@78
     3
preflow_push_max_flow_h
jacint@78
     4
by jacint. 
jacint@78
     5
Runs a preflow push algorithm with the modification, 
jacint@83
     6
that we do not push on nodes with level at least n. 
jacint@83
     7
Moreover, if a level gets empty, we set all nodes above that
jacint@78
     8
level to level n. Hence, in the end, we arrive at a maximum preflow 
jacint@78
     9
with value of a max flow value. An empty level gives a minimum cut.
jacint@78
    10
jacint@78
    11
Member functions:
jacint@78
    12
jacint@78
    13
void run() : runs the algorithm
jacint@78
    14
jacint@78
    15
  The following functions should be used after run() was already run.
jacint@78
    16
jacint@78
    17
T maxflow() : returns the value of a maximum flow
jacint@78
    18
jacint@97
    19
void mincut(CutMap& M) : sets M to the characteristic vector of a 
jacint@97
    20
     minimum cut. M should be a map of bools initialized to false.
jacint@97
    21
jacint@78
    22
*/
jacint@78
    23
jacint@78
    24
#ifndef PREFLOW_PUSH_MAX_FLOW_H
jacint@78
    25
#define PREFLOW_PUSH_MAX_FLOW_H
jacint@78
    26
jacint@97
    27
#define A 1
jacint@97
    28
jacint@78
    29
#include <algorithm>
jacint@78
    30
#include <vector>
jacint@78
    31
#include <stack>
jacint@78
    32
jacint@78
    33
#include <reverse_bfs.h>
jacint@78
    34
jacint@78
    35
jacint@78
    36
namespace marci {
jacint@78
    37
jacint@97
    38
  template <typename Graph, typename T,  
jacint@97
    39
    typename FlowMap=typename Graph::EdgeMap<T>, typename CapMap=typename Graph::EdgeMap<T>, 
jacint@97
    40
    typename IntMap=typename Graph::NodeMap<int>, typename TMap=typename Graph::NodeMap<T> >
jacint@78
    41
  class preflow_push_max_flow {
jacint@78
    42
    
jacint@78
    43
    typedef typename Graph::NodeIt NodeIt;
jacint@78
    44
    typedef typename Graph::EachNodeIt EachNodeIt;
jacint@78
    45
    typedef typename Graph::OutEdgeIt OutEdgeIt;
jacint@78
    46
    typedef typename Graph::InEdgeIt InEdgeIt;
jacint@78
    47
    
jacint@78
    48
    Graph& G;
jacint@78
    49
    NodeIt s;
jacint@78
    50
    NodeIt t;
jacint@97
    51
    IntMap level;
jacint@97
    52
    CapMap& capacity;  
jacint@97
    53
    int empty_level;    //an empty level in the end of run()
jacint@97
    54
    T value; 
jacint@97
    55
    
jacint@78
    56
  public:
jacint@97
    57
      
jacint@97
    58
    preflow_push_max_flow(Graph& _G, NodeIt _s, NodeIt _t, CapMap& _capacity) :
jacint@97
    59
      G(_G), s(_s), t(_t), level(_G), capacity(_capacity) { }
jacint@78
    60
jacint@78
    61
jacint@78
    62
    /*
jacint@83
    63
      The run() function runs a modified version of the 
jacint@83
    64
      highest label preflow-push, which only 
jacint@78
    65
      finds a maximum preflow, hence giving the value of a maximum flow.
jacint@78
    66
    */
jacint@78
    67
    void run() {
jacint@78
    68
 
jacint@97
    69
      int n=G.nodeNum(); 
jacint@78
    70
      int b=n-2; 
jacint@83
    71
      /*
jacint@97
    72
	b is a bound on the highest level of an active node. 
jacint@83
    73
      */
jacint@97
    74
jacint@97
    75
      IntMap level(G,n);      
jacint@97
    76
      TMap excess(G); 
jacint@97
    77
      FlowMap flow(G,0);
jacint@97
    78
jacint@97
    79
      std::vector<int> numb(n);    
jacint@97
    80
      /*
jacint@97
    81
	The number of nodes on level i < n. It is
jacint@97
    82
	initialized to n+1, because of the reverse_bfs-part.
jacint@97
    83
      */
jacint@97
    84
jacint@97
    85
      std::vector<std::stack<NodeIt> > stack(n);    
jacint@97
    86
      //Stack of the active nodes in level i.
jacint@97
    87
jacint@78
    88
jacint@78
    89
      /*Reverse_bfs from t, to find the starting level.*/
jacint@97
    90
      level.set(t,0);
jacint@97
    91
      std::queue<NodeIt> bfs_queue;
jacint@97
    92
      bfs_queue.push(t);
jacint@97
    93
jacint@97
    94
      while (!bfs_queue.empty()) {
jacint@97
    95
jacint@97
    96
	NodeIt v=bfs_queue.front();	
jacint@97
    97
	bfs_queue.pop();
jacint@97
    98
	int l=level.get(v)+1;
jacint@97
    99
jacint@97
   100
	for(InEdgeIt e=G.template first<InEdgeIt>(v); e.valid(); ++e) {
jacint@97
   101
	  NodeIt w=G.tail(e);
jacint@97
   102
	  if ( level.get(w) == n ) {
jacint@97
   103
	    bfs_queue.push(w);
jacint@97
   104
	    ++numb[l];
jacint@97
   105
	    level.set(w, l);
jacint@97
   106
	  }
jacint@78
   107
	}
jacint@97
   108
      }
jacint@97
   109
	
jacint@78
   110
      level.set(s,n);
jacint@78
   111
jacint@97
   112
jacint@97
   113
jacint@97
   114
      /* Starting flow. It is everywhere 0 at the moment. */     
jacint@83
   115
      for(OutEdgeIt e=G.template first<OutEdgeIt>(s); e.valid(); ++e) 
jacint@78
   116
	{
jacint@97
   117
	  if ( capacity.get(e) == 0 ) continue;
jacint@97
   118
	  NodeIt w=G.head(e);
jacint@97
   119
	  if ( level.get(w) < n ) {	  
jacint@97
   120
	    if ( excess.get(w) == 0 && w!=t ) stack[level.get(w)].push(w); 
jacint@83
   121
	    flow.set(e, capacity.get(e)); 
jacint@83
   122
	    excess.set(w, excess.get(w)+capacity.get(e));
jacint@83
   123
	  }
jacint@78
   124
	}
jacint@97
   125
      
jacint@78
   126
      /* 
jacint@78
   127
	 End of preprocessing 
jacint@78
   128
      */
jacint@78
   129
jacint@78
   130
jacint@97
   131
      /*
jacint@97
   132
	Push/relabel on the highest level active nodes.
jacint@97
   133
      */
jacint@97
   134
      /*While there exists an active node.*/
jacint@97
   135
      while (b) { 
jacint@97
   136
	if ( stack[b].empty() ) { 
jacint@97
   137
	  --b;
jacint@97
   138
	  continue;
jacint@97
   139
	} 
jacint@97
   140
	
jacint@97
   141
	NodeIt w=stack[b].top();        //w is a highest label active node.
jacint@97
   142
	stack[b].pop();           
jacint@97
   143
	int lev=level.get(w);
jacint@97
   144
	int exc=excess.get(w);
jacint@97
   145
	int newlevel=2*n-2;      //In newlevel we bound the next level of w.
jacint@97
   146
	
jacint@97
   147
	//  if ( level.get(w) < n ) { //Nem tudom ez mukodik-e
jacint@97
   148
	  for(OutEdgeIt e=G.template first<OutEdgeIt>(w); e.valid(); ++e) {
jacint@97
   149
	    
jacint@97
   150
	    if ( flow.get(e) == capacity.get(e) ) continue; 
jacint@97
   151
	    NodeIt v=G.head(e);            
jacint@97
   152
	    //e=wv	    
jacint@97
   153
	    
jacint@97
   154
	    if( lev > level.get(v) ) {      
jacint@97
   155
	      /*Push is allowed now*/
jacint@97
   156
	      
jacint@97
   157
	      if ( excess.get(v)==0 && v != s && v !=t ) 
jacint@97
   158
		stack[level.get(v)].push(v); 
jacint@97
   159
	      /*v becomes active.*/
jacint@97
   160
	      
jacint@97
   161
	      int cap=capacity.get(e);
jacint@97
   162
	      int flo=flow.get(e);
jacint@97
   163
	      int remcap=cap-flo;
jacint@97
   164
	      
jacint@97
   165
	      if ( remcap >= exc ) {       
jacint@97
   166
		/*A nonsaturating push.*/
jacint@97
   167
		
jacint@97
   168
		flow.set(e, flo+exc);
jacint@97
   169
		excess.set(v, excess.get(v)+exc);
jacint@97
   170
		exc=0;
jacint@97
   171
		break; 
jacint@97
   172
		
jacint@97
   173
	      } else { 
jacint@97
   174
		/*A saturating push.*/
jacint@97
   175
		
jacint@97
   176
		flow.set(e, cap );
jacint@97
   177
		excess.set(v, excess.get(v)+remcap);
jacint@97
   178
		exc-=remcap;
jacint@97
   179
	      }
jacint@97
   180
	    } else if ( newlevel > level.get(v) ) newlevel = level.get(v);
jacint@97
   181
	    
jacint@97
   182
	  } //for out edges wv 
jacint@97
   183
	
jacint@97
   184
	
jacint@97
   185
	if ( exc > 0 ) {	
jacint@97
   186
	  for( InEdgeIt e=G.template first<InEdgeIt>(w); e.valid(); ++e) {
jacint@97
   187
	    
jacint@97
   188
	    if( flow.get(e) == 0 ) continue; 
jacint@97
   189
	    NodeIt v=G.tail(e);  
jacint@97
   190
	    //e=vw
jacint@97
   191
	    
jacint@97
   192
	    if( lev > level.get(v) ) {  
jacint@97
   193
	      /*Push is allowed now*/
jacint@97
   194
	      
jacint@97
   195
	      if ( excess.get(v)==0 && v != s && v !=t) 
jacint@97
   196
		stack[level.get(v)].push(v); 
jacint@97
   197
	      /*v becomes active.*/
jacint@97
   198
	      
jacint@97
   199
	      int flo=flow.get(e);
jacint@97
   200
	      
jacint@97
   201
	      if ( flo >= exc ) { 
jacint@97
   202
		/*A nonsaturating push.*/
jacint@97
   203
		
jacint@97
   204
		flow.set(e, flo-exc);
jacint@97
   205
		excess.set(v, excess.get(v)+exc);
jacint@97
   206
		exc=0;
jacint@97
   207
		break; 
jacint@97
   208
	      } else {                                               
jacint@97
   209
		/*A saturating push.*/
jacint@97
   210
		
jacint@97
   211
		excess.set(v, excess.get(v)+flo);
jacint@97
   212
		exc-=flo;
jacint@97
   213
		flow.set(e,0);
jacint@97
   214
	      }  
jacint@97
   215
	    } else if ( newlevel > level.get(v) ) newlevel = level.get(v);
jacint@97
   216
	    
jacint@97
   217
	  } //for in edges vw
jacint@97
   218
	  
jacint@97
   219
	} // if w still has excess after the out edge for cycle
jacint@97
   220
	
jacint@97
   221
	excess.set(w, exc);
jacint@97
   222
	
jacint@97
   223
	
jacint@97
   224
	/*
jacint@97
   225
	  Relabel
jacint@97
   226
	*/
jacint@97
   227
	  
jacint@97
   228
	if ( exc > 0 ) {
jacint@97
   229
	  //now 'lev' is the old level of w
jacint@97
   230
	  level.set(w,++newlevel);
jacint@97
   231
	  --numb[lev];
jacint@97
   232
	    
jacint@97
   233
	  if ( !numb[lev] && lev < A*n ) {  //If the level of w gets empty. 
jacint@97
   234
	      
jacint@97
   235
	    for (EachNodeIt v=G.template first<EachNodeIt>(); v.valid() ; ++v) {
jacint@97
   236
	      if (level.get(v) > lev ) level.set(v,n);  
jacint@97
   237
	    }
jacint@97
   238
	    for (int i=lev+1 ; i!=n ; ++i) numb[i]=0; 
jacint@97
   239
	    if ( newlevel < n ) newlevel=n; 
jacint@97
   240
	  } else if ( newlevel < n ) {
jacint@97
   241
	    ++numb[newlevel]; 
jacint@97
   242
	    stack[newlevel].push(w);
jacint@97
   243
	    b=newlevel;
jacint@97
   244
	  }
jacint@97
   245
	}
jacint@78
   246
jacint@78
   247
jacint@78
   248
jacint@78
   249
      } //while(b)
jacint@78
   250
jacint@78
   251
      value=excess.get(t);
jacint@78
   252
      /*Max flow value.*/
jacint@78
   253
      
jacint@78
   254
jacint@97
   255
      /* 
jacint@97
   256
	 We count empty_level. The nodes above this level is a mincut.
jacint@78
   257
      */
jacint@97
   258
      while(true) {
jacint@97
   259
	if(numb[empty_level]) ++empty_level;
jacint@78
   260
	else break;
jacint@78
   261
      } 
jacint@78
   262
      
jacint@78
   263
    } // void run()
jacint@78
   264
jacint@78
   265
jacint@78
   266
jacint@78
   267
    /*
jacint@78
   268
      Returns the maximum value of a flow.
jacint@78
   269
     */
jacint@78
   270
jacint@78
   271
    T maxflow() {
jacint@78
   272
      return value;
jacint@78
   273
    }
jacint@78
   274
jacint@78
   275
jacint@78
   276
jacint@78
   277
    /*
jacint@78
   278
      Returns a minimum cut.
jacint@97
   279
    */    
jacint@97
   280
    template<typename CutMap>
jacint@97
   281
    void mincut(CutMap& M) {
jacint@97
   282
jacint@97
   283
      for (EachNodeIt v=G.template first<EachNodeIt>(); v.valid(); ++v) {
jacint@97
   284
	if ( level.get(v) > empty_level ) M.set(v, true);
jacint@97
   285
      }
jacint@78
   286
    }
jacint@97
   287
jacint@78
   288
jacint@78
   289
  };
jacint@78
   290
}//namespace marci
jacint@78
   291
#endif 
jacint@78
   292
jacint@78
   293
jacint@78
   294
jacint@78
   295
jacint@78
   296