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