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