src/work/jacint/preflow_push_hl.h
author marci
Wed, 18 Feb 2004 15:58:28 +0000
changeset 99 f26897fb91fd
parent 88 93bb934b0794
child 101 d2ac583ed195
permissions -rw-r--r--
dfs iterator: DfsIterator4 improved version
jacint@72
     1
// -*- C++ -*-
jacint@72
     2
/*
jacint@83
     3
preflow_push_hl.h
jacint@72
     4
by jacint. 
jacint@72
     5
Runs the highest label variant of the preflow push algorithm with 
jacint@97
     6
running time O(n^2\sqrt(m)), and with the 'empty level' heuristic. 
jacint@97
     7
jacint@97
     8
'A' is a parameter for the empty_level heuristic
jacint@72
     9
jacint@72
    10
Member functions:
jacint@72
    11
jacint@72
    12
void run() : runs the algorithm
jacint@72
    13
jacint@72
    14
 The following functions should be used after run() was already run.
jacint@72
    15
jacint@72
    16
T maxflow() : returns the value of a maximum flow
jacint@72
    17
jacint@83
    18
T flowonedge(EdgeIt e) : for a fixed maximum flow x it returns x(e) 
jacint@72
    19
jacint@97
    20
FlowMap allflow() : returns the fixed maximum flow x
jacint@72
    21
jacint@97
    22
void mincut(CutMap& M) : sets M to the characteristic vector of a 
jacint@97
    23
     minimum cut. M should be a map of bools initialized to false.
jacint@97
    24
jacint@97
    25
void min_mincut(CutMap& M) : sets M to the characteristic vector of the 
jacint@97
    26
     minimum min cut. M should be a map of bools initialized to false.
jacint@97
    27
jacint@97
    28
void max_mincut(CutMap& M) : sets M to the characteristic vector of the 
jacint@97
    29
     maximum min cut. M should be a map of bools initialized to false.
jacint@97
    30
jacint@72
    31
*/
jacint@72
    32
jacint@72
    33
#ifndef PREFLOW_PUSH_HL_H
jacint@72
    34
#define PREFLOW_PUSH_HL_H
jacint@72
    35
jacint@88
    36
#define A 1
jacint@88
    37
jacint@72
    38
#include <vector>
jacint@72
    39
#include <stack>
jacint@97
    40
#include <queue>
jacint@72
    41
jacint@72
    42
namespace marci {
jacint@72
    43
jacint@97
    44
  template <typename Graph, typename T, 
jacint@97
    45
    typename FlowMap=typename Graph::EdgeMap<T>, typename CapMap=typename Graph::EdgeMap<T>, 
jacint@97
    46
    typename IntMap=typename Graph::NodeMap<int>, typename TMap=typename Graph::NodeMap<T> >
jacint@72
    47
  class preflow_push_hl {
jacint@72
    48
    
jacint@72
    49
    typedef typename Graph::NodeIt NodeIt;
jacint@72
    50
    typedef typename Graph::EdgeIt EdgeIt;
jacint@72
    51
    typedef typename Graph::EachNodeIt EachNodeIt;
jacint@72
    52
    typedef typename Graph::OutEdgeIt OutEdgeIt;
jacint@72
    53
    typedef typename Graph::InEdgeIt InEdgeIt;
jacint@72
    54
    
jacint@72
    55
    Graph& G;
jacint@72
    56
    NodeIt s;
jacint@72
    57
    NodeIt t;
jacint@97
    58
    FlowMap flow;
jacint@97
    59
    CapMap& capacity;  
jacint@72
    60
    T value;
jacint@97
    61
    
jacint@72
    62
  public:
jacint@72
    63
jacint@97
    64
    preflow_push_hl(Graph& _G, NodeIt _s, NodeIt _t, CapMap& _capacity) :
jacint@97
    65
      G(_G), s(_s), t(_t), flow(_G, 0), capacity(_capacity) { }
jacint@72
    66
jacint@72
    67
jacint@97
    68
    
jacint@97
    69
jacint@72
    70
    void run() {
jacint@72
    71
 
jacint@84
    72
      int n=G.nodeNum(); 
jacint@83
    73
      int b=n-2; 
jacint@83
    74
      /*
jacint@83
    75
	b is a bound on the highest level of an active node. 
jacint@83
    76
      */
jacint@72
    77
jacint@97
    78
      IntMap level(G,n);      
jacint@97
    79
      TMap excess(G); 
jacint@97
    80
jacint@97
    81
      std::vector<int> numb(n);    
jacint@97
    82
      /*
jacint@97
    83
	The number of nodes on level i < n. It is
jacint@97
    84
	initialized to n+1, because of the reverse_bfs-part.
jacint@97
    85
      */
jacint@97
    86
jacint@83
    87
      std::vector<std::stack<NodeIt> > stack(2*n-1);    
jacint@83
    88
      //Stack of the active nodes in level i.
jacint@72
    89
jacint@72
    90
jacint@72
    91
      /*Reverse_bfs from t, to find the starting level.*/
jacint@97
    92
      level.set(t,0);
jacint@97
    93
      std::queue<NodeIt> bfs_queue;
jacint@97
    94
      bfs_queue.push(t);
jacint@97
    95
jacint@97
    96
      while (!bfs_queue.empty()) {
jacint@97
    97
jacint@97
    98
	NodeIt v=bfs_queue.front();	
jacint@97
    99
	bfs_queue.pop();
jacint@97
   100
	int l=level.get(v)+1;
jacint@97
   101
jacint@97
   102
	for(InEdgeIt e=G.template first<InEdgeIt>(v); e.valid(); ++e) {
jacint@97
   103
	  NodeIt w=G.tail(e);
jacint@97
   104
	  if ( level.get(w) == n ) {
jacint@97
   105
	    bfs_queue.push(w);
jacint@97
   106
	    ++numb[l];
jacint@97
   107
	    level.set(w, l);
jacint@97
   108
	  }
jacint@83
   109
	}
jacint@97
   110
      }
jacint@97
   111
	
jacint@97
   112
      level.set(s,n);
jacint@72
   113
jacint@72
   114
jacint@72
   115
jacint@83
   116
      /* Starting flow. It is everywhere 0 at the moment. */     
jacint@83
   117
      for(OutEdgeIt e=G.template first<OutEdgeIt>(s); e.valid(); ++e) 
jacint@72
   118
	{
jacint@97
   119
	  if ( capacity.get(e) == 0 ) continue;
jacint@97
   120
	  NodeIt w=G.head(e);
jacint@97
   121
	  if ( w!=s ) {	  
jacint@97
   122
	    if ( excess.get(w) == 0 && w!=t ) stack[level.get(w)].push(w); 
jacint@97
   123
	    flow.set(e, capacity.get(e)); 
jacint@97
   124
	    excess.set(w, excess.get(w)+capacity.get(e));
jacint@83
   125
	  }
jacint@72
   126
	}
jacint@97
   127
      
jacint@72
   128
      /* 
jacint@72
   129
	 End of preprocessing 
jacint@72
   130
      */
jacint@72
   131
jacint@72
   132
jacint@72
   133
      /*
jacint@84
   134
	Push/relabel on the highest level active nodes.
jacint@72
   135
      */
jacint@85
   136
      /*While there exists an active node.*/
jacint@72
   137
      while (b) { 
jacint@97
   138
	if ( stack[b].empty() ) { 
jacint@72
   139
	  --b;
jacint@97
   140
	  continue;
jacint@97
   141
	} 
jacint@72
   142
	
jacint@97
   143
	NodeIt w=stack[b].top();        //w is a highest label active node.
jacint@97
   144
	stack[b].pop();           
jacint@97
   145
	int lev=level.get(w);
jacint@97
   146
	int exc=excess.get(w);
jacint@97
   147
	int newlevel=2*n-2;      //In newlevel we bound the next level of w.
jacint@72
   148
	
jacint@97
   149
	//  if ( level.get(w) < n ) { //Nem tudom ez mukodik-e
jacint@72
   150
	  for(OutEdgeIt e=G.template first<OutEdgeIt>(w); e.valid(); ++e) {
jacint@84
   151
	    
jacint@97
   152
	    if ( flow.get(e) == capacity.get(e) ) continue; 
jacint@97
   153
	    NodeIt v=G.head(e);            
jacint@97
   154
	    //e=wv	    
jacint@97
   155
	    
jacint@97
   156
	    if( lev > level.get(v) ) {      
jacint@97
   157
	      /*Push is allowed now*/
jacint@97
   158
	      
jacint@97
   159
	      if ( excess.get(v)==0 && v != s && v !=t ) 
jacint@97
   160
		stack[level.get(v)].push(v); 
jacint@97
   161
	      /*v becomes active.*/
jacint@97
   162
	      
jacint@97
   163
	      int cap=capacity.get(e);
jacint@97
   164
	      int flo=flow.get(e);
jacint@97
   165
	      int remcap=cap-flo;
jacint@97
   166
	      
jacint@97
   167
	      if ( remcap >= exc ) {       
jacint@97
   168
		/*A nonsaturating push.*/
jacint@97
   169
		
jacint@97
   170
		flow.set(e, flo+exc);
jacint@97
   171
		excess.set(v, excess.get(v)+exc);
jacint@97
   172
		exc=0;
jacint@97
   173
		break; 
jacint@97
   174
		
jacint@97
   175
	      } else { 
jacint@97
   176
		/*A saturating push.*/
jacint@97
   177
		
jacint@97
   178
		flow.set(e, cap );
jacint@97
   179
		excess.set(v, excess.get(v)+remcap);
jacint@97
   180
		exc-=remcap;
jacint@97
   181
	      }
jacint@97
   182
	    } else if ( newlevel > level.get(v) ) newlevel = level.get(v);
jacint@97
   183
	    
jacint@97
   184
	  } //for out edges wv 
jacint@97
   185
	
jacint@97
   186
	
jacint@97
   187
	if ( exc > 0 ) {	
jacint@97
   188
	  for( InEdgeIt e=G.template first<InEdgeIt>(w); e.valid(); ++e) {
jacint@97
   189
	    
jacint@97
   190
	    if( flow.get(e) == 0 ) continue; 
jacint@97
   191
	    NodeIt v=G.tail(e);  
jacint@97
   192
	    //e=vw
jacint@97
   193
	    
jacint@97
   194
	    if( lev > level.get(v) ) {  
jacint@97
   195
	      /*Push is allowed now*/
jacint@97
   196
	      
jacint@97
   197
	      if ( excess.get(v)==0 && v != s && v !=t) 
jacint@97
   198
		stack[level.get(v)].push(v); 
jacint@97
   199
	      /*v becomes active.*/
jacint@97
   200
	      
jacint@97
   201
	      int flo=flow.get(e);
jacint@97
   202
	      
jacint@97
   203
	      if ( flo >= exc ) { 
jacint@97
   204
		/*A nonsaturating push.*/
jacint@97
   205
		
jacint@97
   206
		flow.set(e, flo-exc);
jacint@97
   207
		excess.set(v, excess.get(v)+exc);
jacint@97
   208
		exc=0;
jacint@97
   209
		break; 
jacint@97
   210
	      } else {                                               
jacint@97
   211
		/*A saturating push.*/
jacint@97
   212
		
jacint@97
   213
		excess.set(v, excess.get(v)+flo);
jacint@97
   214
		exc-=flo;
jacint@97
   215
		flow.set(e,0);
jacint@97
   216
	      }  
jacint@97
   217
	    } else if ( newlevel > level.get(v) ) newlevel = level.get(v);
jacint@97
   218
	    
jacint@97
   219
	  } //for in edges vw
jacint@97
   220
	  
jacint@97
   221
	} // if w still has excess after the out edge for cycle
jacint@97
   222
	
jacint@97
   223
	excess.set(w, exc);
jacint@97
   224
	
jacint@72
   225
jacint@97
   226
	
jacint@72
   227
jacint@97
   228
	/*
jacint@97
   229
	  Relabel
jacint@97
   230
	*/
jacint@97
   231
	
jacint@97
   232
	if ( exc > 0 ) {
jacint@97
   233
	  //now 'lev' is the old level of w
jacint@97
   234
	  level.set(w,++newlevel);
jacint@97
   235
	  
jacint@97
   236
	  if ( lev < n ) {
jacint@97
   237
	    --numb[lev];
jacint@97
   238
	    
jacint@97
   239
	    if ( !numb[lev] && lev < A*n ) {  //If the level of w gets empty. 
jacint@97
   240
	      
jacint@97
   241
	      for (EachNodeIt v=G.template first<EachNodeIt>(); v.valid() ; ++v) {
jacint@97
   242
		if (level.get(v) > lev && level.get(v) < n ) level.set(v,n);  
jacint@85
   243
	      }
jacint@97
   244
	      for (int i=lev+1 ; i!=n ; ++i) numb[i]=0; 
jacint@97
   245
	      if ( newlevel < n ) newlevel=n; 
jacint@97
   246
	    } else { 
jacint@97
   247
	      if ( newlevel < n ) ++numb[newlevel]; 
jacint@97
   248
	    }
jacint@97
   249
	  } 
jacint@72
   250
	  
jacint@97
   251
	  stack[newlevel].push(w);
jacint@97
   252
	  b=newlevel;
jacint@85
   253
	  
jacint@97
   254
	}
jacint@97
   255
	
jacint@85
   256
      } // while(b)
jacint@97
   257
      
jacint@97
   258
      
jacint@72
   259
      value = excess.get(t);
jacint@72
   260
      /*Max flow value.*/
jacint@72
   261
jacint@72
   262
jacint@72
   263
    } //void run()
jacint@72
   264
jacint@72
   265
jacint@72
   266
jacint@72
   267
jacint@72
   268
jacint@72
   269
    /*
jacint@72
   270
      Returns the maximum value of a flow.
jacint@72
   271
     */
jacint@72
   272
jacint@72
   273
    T maxflow() {
jacint@72
   274
      return value;
jacint@72
   275
    }
jacint@72
   276
jacint@72
   277
jacint@72
   278
jacint@72
   279
    /*
jacint@72
   280
      For the maximum flow x found by the algorithm, it returns the flow value on Edge e, i.e. x(e). 
jacint@72
   281
    */
jacint@72
   282
jacint@97
   283
    T flowonedge(const EdgeIt e) {
jacint@72
   284
      return flow.get(e);
jacint@72
   285
    }
jacint@72
   286
jacint@72
   287
jacint@72
   288
jacint@72
   289
    /*
jacint@72
   290
      Returns the maximum flow x found by the algorithm.
jacint@72
   291
    */
jacint@72
   292
jacint@97
   293
    FlowMap allflow() {
jacint@72
   294
      return flow;
jacint@72
   295
    }
jacint@72
   296
jacint@72
   297
jacint@72
   298
jacint@97
   299
jacint@72
   300
    /*
jacint@97
   301
      Returns the minimum min cut, by a bfs from s in the residual graph.
jacint@72
   302
    */
jacint@72
   303
    
jacint@97
   304
    template<typename CutMap>
jacint@97
   305
    void mincut(CutMap& M) {
jacint@72
   306
    
jacint@72
   307
      std::queue<NodeIt> queue;
jacint@72
   308
      
jacint@97
   309
      M.set(s,true);      
jacint@97
   310
      queue.push(s);
jacint@97
   311
jacint@97
   312
      while (!queue.empty()) {
jacint@97
   313
        NodeIt w=queue.front();
jacint@97
   314
	queue.pop();
jacint@97
   315
	
jacint@97
   316
	for(OutEdgeIt e=G.template first<OutEdgeIt>(w) ; e.valid(); ++e) {
jacint@97
   317
	  NodeIt v=G.head(e);
jacint@97
   318
	  if (!M.get(v) && flow.get(e) < capacity.get(e) ) {
jacint@97
   319
	    queue.push(v);
jacint@97
   320
	    M.set(v, true);
jacint@97
   321
	  }
jacint@97
   322
	} 
jacint@97
   323
jacint@97
   324
	for(InEdgeIt e=G.template first<InEdgeIt>(w) ; e.valid(); ++e) {
jacint@97
   325
	  NodeIt v=G.tail(e);
jacint@97
   326
	  if (!M.get(v) && flow.get(e) > 0 ) {
jacint@97
   327
	    queue.push(v);
jacint@97
   328
	    M.set(v, true);
jacint@97
   329
	  }
jacint@97
   330
	}
jacint@97
   331
jacint@97
   332
      }
jacint@97
   333
    }
jacint@97
   334
jacint@97
   335
jacint@97
   336
jacint@97
   337
    /*
jacint@97
   338
      Returns the maximum min cut, by a reverse bfs 
jacint@97
   339
      from t in the residual graph.
jacint@97
   340
    */
jacint@97
   341
    
jacint@97
   342
    template<typename CutMap>
jacint@97
   343
    void max_mincut(CutMap& M) {
jacint@97
   344
    
jacint@97
   345
      std::queue<NodeIt> queue;
jacint@97
   346
      
jacint@97
   347
      M.set(t,true);        
jacint@72
   348
      queue.push(t);
jacint@72
   349
jacint@72
   350
      while (!queue.empty()) {
jacint@72
   351
        NodeIt w=queue.front();
jacint@72
   352
	queue.pop();
jacint@72
   353
jacint@72
   354
	for(InEdgeIt e=G.template first<InEdgeIt>(w) ; e.valid(); ++e) {
jacint@72
   355
	  NodeIt v=G.tail(e);
jacint@97
   356
	  if (!M.get(v) && flow.get(e) < capacity.get(e) ) {
jacint@72
   357
	    queue.push(v);
jacint@97
   358
	    M.set(v, true);
jacint@72
   359
	  }
jacint@97
   360
	}
jacint@72
   361
jacint@72
   362
	for(OutEdgeIt e=G.template first<OutEdgeIt>(w) ; e.valid(); ++e) {
jacint@72
   363
	  NodeIt v=G.head(e);
jacint@97
   364
	  if (!M.get(v) && flow.get(e) > 0 ) {
jacint@72
   365
	    queue.push(v);
jacint@97
   366
	    M.set(v, true);
jacint@72
   367
	  }
jacint@97
   368
	}
jacint@72
   369
      }
jacint@72
   370
jacint@97
   371
      for(EachNodeIt v=G.template first<EachNodeIt>() ; v.valid(); ++v) {
jacint@97
   372
	M.set(v, !M.get(v));
jacint@97
   373
      }
jacint@97
   374
jacint@72
   375
    }
jacint@97
   376
jacint@97
   377
jacint@97
   378
jacint@97
   379
    template<typename CutMap>
jacint@97
   380
    void min_mincut(CutMap& M) {
jacint@97
   381
      mincut(M);
jacint@97
   382
    }
jacint@97
   383
jacint@97
   384
jacint@97
   385
jacint@72
   386
  };
jacint@72
   387
}//namespace marci
jacint@72
   388
#endif 
jacint@72
   389
jacint@72
   390
jacint@72
   391
jacint@72
   392