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