src/work/jacint/preflow.h
author marci
Thu, 29 Apr 2004 10:16:46 +0000
changeset 466 cd40ecf4d2a9
parent 465 d72e56f1730d
child 468 3a2cb784750a
permissions -rw-r--r--
preflow, maxflow comp
jacint@109
     1
// -*- C++ -*-
jacint@372
     2
jacint@109
     3
/*
jacint@109
     4
Heuristics: 
jacint@109
     5
 2 phase
jacint@109
     6
 gap
jacint@109
     7
 list 'level_list' on the nodes on level i implemented by hand
jacint@451
     8
 stack 'active' on the active nodes on level i
jacint@109
     9
 runs heuristic 'highest label' for H1*n relabels
jacint@113
    10
 runs heuristic 'bound decrease' for H0*n relabels, starts with 'highest label'
jacint@109
    11
 
jacint@451
    12
Parameters H0 and H1 are initialized to 20 and 1.
jacint@109
    13
jacint@211
    14
Constructors:
jacint@109
    15
jacint@372
    16
Preflow(Graph, Node, Node, CapMap, FlowMap, bool) : bool must be false if 
jacint@372
    17
     FlowMap is not constant zero, and should be true if it is
jacint@109
    18
jacint@109
    19
Members:
jacint@109
    20
jacint@211
    21
void run()
jacint@109
    22
jacint@211
    23
T flowValue() : returns the value of a maximum flow
jacint@109
    24
jacint@109
    25
void minMinCut(CutMap& M) : sets M to the characteristic vector of the 
jacint@451
    26
     minimum min cut. M should be a map of bools initialized to false. ??Is it OK?
jacint@109
    27
jacint@109
    28
void maxMinCut(CutMap& M) : sets M to the characteristic vector of the 
jacint@109
    29
     maximum min cut. M should be a map of bools initialized to false.
jacint@109
    30
jacint@109
    31
void minCut(CutMap& M) : sets M to the characteristic vector of 
jacint@109
    32
     a min cut. M should be a map of bools initialized to false.
jacint@109
    33
jacint@109
    34
*/
jacint@109
    35
jacint@211
    36
#ifndef HUGO_PREFLOW_H
jacint@211
    37
#define HUGO_PREFLOW_H
jacint@109
    38
jacint@109
    39
#define H0 20
jacint@109
    40
#define H1 1
jacint@109
    41
jacint@109
    42
#include <vector>
jacint@109
    43
#include <queue>
jacint@451
    44
#include <stack>
jacint@109
    45
jacint@109
    46
namespace hugo {
jacint@109
    47
jacint@109
    48
  template <typename Graph, typename T, 
marci@389
    49
	    typename CapMap=typename Graph::template EdgeMap<T>, 
marci@389
    50
            typename FlowMap=typename Graph::template EdgeMap<T> >
jacint@211
    51
  class Preflow {
jacint@109
    52
    
jacint@211
    53
    typedef typename Graph::Node Node;
jacint@109
    54
    typedef typename Graph::NodeIt NodeIt;
jacint@109
    55
    typedef typename Graph::OutEdgeIt OutEdgeIt;
jacint@109
    56
    typedef typename Graph::InEdgeIt InEdgeIt;
jacint@451
    57
jacint@451
    58
    typedef typename std::vector<std::stack<Node> > VecStack;
jacint@451
    59
    typedef typename Graph::template NodeMap<Node> NNMap;
jacint@451
    60
    typedef typename std::vector<Node> VecNode;
jacint@451
    61
marci@466
    62
    const Graph* g;
jacint@211
    63
    Node s;
jacint@211
    64
    Node t;
marci@465
    65
    const CapMap* capacity;  
jacint@451
    66
    FlowMap* flow;
jacint@451
    67
    int n;      //the number of nodes of G
jacint@451
    68
    typename Graph::template NodeMap<int> level;      
jacint@451
    69
    typename Graph::template NodeMap<T> excess; 
jacint@451
    70
jacint@109
    71
jacint@109
    72
  public:
jacint@451
    73
 
jacint@451
    74
    enum flowEnum{
jacint@451
    75
      ZERO_FLOW=0,
jacint@451
    76
      GEN_FLOW=1,
jacint@451
    77
      PREFLOW=2
jacint@451
    78
    };
jacint@451
    79
marci@465
    80
    Preflow(const Graph& _G, Node _s, Node _t, const CapMap& _capacity, 
jacint@451
    81
	    FlowMap& _flow) :
marci@466
    82
      g(&_G), s(_s), t(_t), capacity(&_capacity), 
jacint@451
    83
      flow(&_flow), n(_G.nodeNum()), level(_G), excess(_G,0) {}
jacint@451
    84
jacint@451
    85
    void run() {
jacint@451
    86
      preflow( ZERO_FLOW );
jacint@451
    87
    }
jacint@372
    88
    
jacint@451
    89
    void preflow( flowEnum fe ) {
jacint@451
    90
      preflowPhase0(fe);
jacint@451
    91
      preflowPhase1();
jacint@451
    92
    }
jacint@451
    93
jacint@451
    94
    void preflowPhase0( flowEnum fe ) {
jacint@372
    95
      
jacint@109
    96
      int heur0=(int)(H0*n);  //time while running 'bound decrease' 
jacint@109
    97
      int heur1=(int)(H1*n);  //time while running 'highest label'
jacint@109
    98
      int heur=heur1;         //starting time interval (#of relabels)
jacint@451
    99
      int numrelabel=0;
jacint@451
   100
     
jacint@109
   101
      bool what_heur=1;       
jacint@451
   102
      //It is 0 in case 'bound decrease' and 1 in case 'highest label'
jacint@451
   103
jacint@109
   104
      bool end=false;     
jacint@451
   105
      //Needed for 'bound decrease', true means no active nodes are above bound b.
jacint@451
   106
jacint@109
   107
      int k=n-2;  //bound on the highest level under n containing a node
jacint@109
   108
      int b=k;    //bound on the highest level under n of an active node
jacint@109
   109
      
jacint@451
   110
      VecStack active(n);
jacint@451
   111
      
marci@466
   112
      NNMap left(*g, INVALID);
marci@466
   113
      NNMap right(*g, INVALID);
jacint@451
   114
      VecNode level_list(n,INVALID);
jacint@451
   115
      //List of the nodes in level i<n, set to n.
jacint@109
   116
jacint@451
   117
      NodeIt v;
marci@466
   118
      for(g->first(v); g->valid(v); g->next(v)) level.set(v,n);
jacint@451
   119
      //setting each node to level n
jacint@451
   120
      
jacint@451
   121
      switch ( fe ) {
jacint@451
   122
      case PREFLOW:
jacint@451
   123
	{
jacint@451
   124
	  //counting the excess
jacint@451
   125
	  NodeIt v;
marci@466
   126
	  for(g->first(v); g->valid(v); g->next(v)) {
jacint@451
   127
	    T exc=0;
jacint@372
   128
	  
jacint@451
   129
	    InEdgeIt e;
marci@466
   130
	    for(g->first(e,v); g->valid(e); g->next(e)) exc+=(*flow)[e];
jacint@451
   131
	    OutEdgeIt f;
marci@466
   132
	    for(g->first(f,v); g->valid(f); g->next(f)) exc-=(*flow)[f];
jacint@451
   133
	    
jacint@451
   134
	    excess.set(v,exc);	  
jacint@451
   135
	    
jacint@451
   136
	    //putting the active nodes into the stack
jacint@451
   137
	    int lev=level[v];
jacint@451
   138
	    if ( exc > 0 && lev < n && v != t ) active[lev].push(v);
jacint@451
   139
	  }
jacint@451
   140
	  break;
jacint@451
   141
	}
jacint@451
   142
      case GEN_FLOW:
jacint@451
   143
	{
jacint@451
   144
	  //Counting the excess of t
jacint@451
   145
	  T exc=0;
jacint@372
   146
	  
jacint@372
   147
	  InEdgeIt e;
marci@466
   148
	  for(g->first(e,t); g->valid(e); g->next(e)) exc+=(*flow)[e];
jacint@451
   149
	  OutEdgeIt f;
marci@466
   150
	  for(g->first(f,t); g->valid(f); g->next(f)) exc-=(*flow)[f];
jacint@451
   151
	  
jacint@451
   152
	  excess.set(t,exc);	
jacint@451
   153
	  
jacint@451
   154
	  break;
jacint@451
   155
	}
marci@465
   156
//       default:
marci@465
   157
// 	break;
marci@465
   158
// 	ZERO_FLOW ize kell
marci@465
   159
jacint@451
   160
      }
jacint@451
   161
      
jacint@451
   162
      preflowPreproc( fe, active, level_list, left, right );
jacint@451
   163
      //End of preprocessing 
jacint@451
   164
      
jacint@451
   165
      
jacint@451
   166
      //Push/relabel on the highest level active nodes.
jacint@451
   167
      while ( true ) {
jacint@451
   168
	if ( b == 0 ) {
jacint@451
   169
	  if ( !what_heur && !end && k > 0 ) {
jacint@451
   170
	    b=k;
jacint@451
   171
	    end=true;
jacint@451
   172
	  } else break;
jacint@451
   173
	}
jacint@451
   174
	
jacint@451
   175
	if ( active[b].empty() ) --b; 
jacint@451
   176
	else {
jacint@451
   177
	  end=false;  
jacint@451
   178
	  Node w=active[b].top();
jacint@451
   179
	  active[b].pop();
jacint@451
   180
	  int newlevel=push(w,active);
jacint@451
   181
	  if ( excess[w] > 0 ) relabel(w, newlevel, active, level_list, 
jacint@451
   182
				       left, right, b, k, what_heur);
jacint@451
   183
	  
jacint@451
   184
	  ++numrelabel; 
jacint@451
   185
	  if ( numrelabel >= heur ) {
jacint@451
   186
	    numrelabel=0;
jacint@451
   187
	    if ( what_heur ) {
jacint@451
   188
	      what_heur=0;
jacint@451
   189
	      heur=heur0;
jacint@451
   190
	      end=false;
jacint@451
   191
	    } else {
jacint@451
   192
	      what_heur=1;
jacint@451
   193
	      heur=heur1;
jacint@451
   194
	      b=k; 
jacint@372
   195
	    }
jacint@109
   196
	  }
jacint@451
   197
	} 
jacint@451
   198
      } 
jacint@451
   199
    }
jacint@451
   200
jacint@451
   201
jacint@451
   202
    void preflowPhase1() {
jacint@451
   203
      
jacint@451
   204
      int k=n-2;  //bound on the highest level under n containing a node
jacint@451
   205
      int b=k;    //bound on the highest level under n of an active node
jacint@451
   206
      
jacint@451
   207
      VecStack active(n);
jacint@451
   208
      level.set(s,0);
jacint@451
   209
      std::queue<Node> bfs_queue;
jacint@451
   210
      bfs_queue.push(s);
jacint@451
   211
	    
jacint@451
   212
      while (!bfs_queue.empty()) {
jacint@451
   213
	
jacint@451
   214
	Node v=bfs_queue.front();	
jacint@451
   215
	bfs_queue.pop();
jacint@451
   216
	int l=level[v]+1;
jacint@451
   217
	      
jacint@451
   218
	InEdgeIt e;
marci@466
   219
	for(g->first(e,v); g->valid(e); g->next(e)) {
jacint@451
   220
	  if ( (*capacity)[e] == (*flow)[e] ) continue;
marci@466
   221
	  Node u=g->tail(e);
jacint@451
   222
	  if ( level[u] >= n ) { 
jacint@451
   223
	    bfs_queue.push(u);
jacint@451
   224
	    level.set(u, l);
jacint@451
   225
	    if ( excess[u] > 0 ) active[l].push(u);
jacint@451
   226
	  }
jacint@109
   227
	}
jacint@451
   228
	
jacint@451
   229
	OutEdgeIt f;
marci@466
   230
	for(g->first(f,v); g->valid(f); g->next(f)) {
jacint@451
   231
	  if ( 0 == (*flow)[f] ) continue;
marci@466
   232
	  Node u=g->head(f);
jacint@451
   233
	  if ( level[u] >= n ) { 
jacint@451
   234
	    bfs_queue.push(u);
jacint@451
   235
	    level.set(u, l);
jacint@451
   236
	    if ( excess[u] > 0 ) active[l].push(u);
jacint@109
   237
	  }
jacint@109
   238
	}
jacint@372
   239
      }
jacint@451
   240
      b=n-2;
jacint@372
   241
jacint@109
   242
      while ( true ) {
jacint@109
   243
	
jacint@451
   244
	if ( b == 0 ) break;
jacint@451
   245
jacint@451
   246
	if ( active[b].empty() ) --b; 
jacint@109
   247
	else {
jacint@451
   248
	  Node w=active[b].top();
jacint@451
   249
	  active[b].pop();
jacint@451
   250
	  int newlevel=push(w,active);	  
jacint@109
   251
jacint@451
   252
	  //relabel
jacint@451
   253
	  if ( excess[w] > 0 ) {
jacint@109
   254
	    level.set(w,++newlevel);
jacint@451
   255
	    active[newlevel].push(w);
jacint@109
   256
	    b=newlevel;
jacint@451
   257
	  }
jacint@109
   258
	}  // if stack[b] is nonempty
jacint@109
   259
      } // while(true)
jacint@109
   260
    }
jacint@109
   261
jacint@109
   262
jacint@451
   263
    //Returns the maximum value of a flow.
jacint@451
   264
    T flowValue() {
jacint@451
   265
      return excess[t];
jacint@451
   266
    }
jacint@109
   267
jacint@451
   268
    //should be used only between preflowPhase0 and preflowPhase1
jacint@451
   269
    template<typename _CutMap>
jacint@451
   270
    void actMinCut(_CutMap& M) {
jacint@211
   271
      NodeIt v;
marci@466
   272
      for(g->first(v); g->valid(v); g->next(v)) 
marci@466
   273
      if ( level[v] < n ) {
marci@466
   274
	M.set(v,false);
marci@466
   275
      } else {
marci@466
   276
	M.set(v,true);
marci@466
   277
      }
jacint@211
   278
    }
jacint@109
   279
jacint@109
   280
jacint@109
   281
jacint@109
   282
    /*
jacint@109
   283
      Returns the minimum min cut, by a bfs from s in the residual graph.
jacint@109
   284
    */
jacint@109
   285
    template<typename _CutMap>
jacint@109
   286
    void minMinCut(_CutMap& M) {
jacint@109
   287
    
jacint@211
   288
      std::queue<Node> queue;
jacint@109
   289
      
jacint@109
   290
      M.set(s,true);      
jacint@109
   291
      queue.push(s);
jacint@109
   292
jacint@109
   293
      while (!queue.empty()) {
jacint@211
   294
        Node w=queue.front();
jacint@109
   295
	queue.pop();
jacint@109
   296
jacint@211
   297
	OutEdgeIt e;
marci@466
   298
	for(g->first(e,w) ; g->valid(e); g->next(e)) {
marci@466
   299
	  Node v=g->head(e);
jacint@451
   300
	  if (!M[v] && (*flow)[e] < (*capacity)[e] ) {
jacint@109
   301
	    queue.push(v);
jacint@109
   302
	    M.set(v, true);
jacint@109
   303
	  }
jacint@109
   304
	} 
jacint@109
   305
jacint@211
   306
	InEdgeIt f;
marci@466
   307
	for(g->first(f,w) ; g->valid(f); g->next(f)) {
marci@466
   308
	  Node v=g->tail(f);
jacint@451
   309
	  if (!M[v] && (*flow)[f] > 0 ) {
jacint@109
   310
	    queue.push(v);
jacint@109
   311
	    M.set(v, true);
jacint@109
   312
	  }
jacint@109
   313
	} 
jacint@109
   314
      }
jacint@109
   315
    }
jacint@109
   316
jacint@109
   317
jacint@109
   318
  
jacint@109
   319
    /*
jacint@109
   320
      Returns the maximum min cut, by a reverse bfs 
jacint@109
   321
      from t in the residual graph.
jacint@109
   322
    */
jacint@109
   323
    
jacint@109
   324
    template<typename _CutMap>
jacint@109
   325
    void maxMinCut(_CutMap& M) {
jacint@451
   326
jacint@451
   327
      NodeIt v;
marci@466
   328
      for(g->first(v) ; g->valid(v); g->next(v)) {
jacint@451
   329
	M.set(v, true);
jacint@451
   330
      }
jacint@451
   331
jacint@211
   332
      std::queue<Node> queue;
jacint@109
   333
      
jacint@451
   334
      M.set(t,false);        
jacint@109
   335
      queue.push(t);
jacint@109
   336
jacint@109
   337
      while (!queue.empty()) {
jacint@211
   338
        Node w=queue.front();
jacint@109
   339
	queue.pop();
jacint@109
   340
jacint@211
   341
jacint@211
   342
	InEdgeIt e;
marci@466
   343
	for(g->first(e,w) ; g->valid(e); g->next(e)) {
marci@466
   344
	  Node v=g->tail(e);
jacint@451
   345
	  if (M[v] && (*flow)[e] < (*capacity)[e] ) {
jacint@109
   346
	    queue.push(v);
jacint@451
   347
	    M.set(v, false);
jacint@109
   348
	  }
jacint@109
   349
	}
jacint@211
   350
	
jacint@211
   351
	OutEdgeIt f;
marci@466
   352
	for(g->first(f,w) ; g->valid(f); g->next(f)) {
marci@466
   353
	  Node v=g->head(f);
jacint@451
   354
	  if (M[v] && (*flow)[f] > 0 ) {
jacint@109
   355
	    queue.push(v);
jacint@451
   356
	    M.set(v, false);
jacint@109
   357
	  }
jacint@109
   358
	}
jacint@109
   359
      }
jacint@109
   360
    }
jacint@109
   361
jacint@109
   362
jacint@109
   363
    template<typename CutMap>
jacint@109
   364
    void minCut(CutMap& M) {
jacint@109
   365
      minMinCut(M);
jacint@109
   366
    }
jacint@109
   367
jacint@372
   368
    
jacint@451
   369
    void resetTarget (const Node _t) {t=_t;}
jacint@451
   370
jacint@451
   371
    void resetSource (const Node _s) {s=_s;}
jacint@372
   372
   
jacint@451
   373
    void resetCap (const CapMap& _cap) {
jacint@451
   374
      capacity=&_cap;
jacint@451
   375
    }
jacint@451
   376
    
jacint@451
   377
    void resetFlow (FlowMap& _flow) {
jacint@451
   378
      flow=&_flow;
jacint@372
   379
    }
jacint@372
   380
jacint@372
   381
jacint@451
   382
  private:
jacint@451
   383
jacint@451
   384
    int push(const Node w, VecStack& active) {
jacint@451
   385
      
jacint@451
   386
      int lev=level[w];
jacint@451
   387
      T exc=excess[w];
jacint@451
   388
      int newlevel=n;       //bound on the next level of w
jacint@451
   389
	  
jacint@451
   390
      OutEdgeIt e;
marci@466
   391
      for(g->first(e,w); g->valid(e); g->next(e)) {
jacint@451
   392
	    
jacint@451
   393
	if ( (*flow)[e] == (*capacity)[e] ) continue; 
marci@466
   394
	Node v=g->head(e);            
jacint@451
   395
	    
jacint@451
   396
	if( lev > level[v] ) { //Push is allowed now
jacint@451
   397
	  
jacint@451
   398
	  if ( excess[v]==0 && v!=t && v!=s ) {
jacint@451
   399
	    int lev_v=level[v];
jacint@451
   400
	    active[lev_v].push(v);
jacint@451
   401
	  }
jacint@451
   402
	  
jacint@451
   403
	  T cap=(*capacity)[e];
jacint@451
   404
	  T flo=(*flow)[e];
jacint@451
   405
	  T remcap=cap-flo;
jacint@451
   406
	  
jacint@451
   407
	  if ( remcap >= exc ) { //A nonsaturating push.
jacint@451
   408
	    
jacint@451
   409
	    flow->set(e, flo+exc);
jacint@451
   410
	    excess.set(v, excess[v]+exc);
jacint@451
   411
	    exc=0;
jacint@451
   412
	    break; 
jacint@451
   413
	    
jacint@451
   414
	  } else { //A saturating push.
jacint@451
   415
	    flow->set(e, cap);
jacint@451
   416
	    excess.set(v, excess[v]+remcap);
jacint@451
   417
	    exc-=remcap;
jacint@451
   418
	  }
jacint@451
   419
	} else if ( newlevel > level[v] ) newlevel = level[v];
jacint@451
   420
      } //for out edges wv 
jacint@451
   421
      
jacint@451
   422
      if ( exc > 0 ) {	
jacint@451
   423
	InEdgeIt e;
marci@466
   424
	for(g->first(e,w); g->valid(e); g->next(e)) {
jacint@451
   425
	  
jacint@451
   426
	  if( (*flow)[e] == 0 ) continue; 
marci@466
   427
	  Node v=g->tail(e); 
jacint@451
   428
	  
jacint@451
   429
	  if( lev > level[v] ) { //Push is allowed now
jacint@451
   430
	    
jacint@451
   431
	    if ( excess[v]==0 && v!=t && v!=s ) {
jacint@451
   432
	      int lev_v=level[v];
jacint@451
   433
	      active[lev_v].push(v);
jacint@451
   434
	    }
jacint@451
   435
	    
jacint@451
   436
	    T flo=(*flow)[e];
jacint@451
   437
	    
jacint@451
   438
	    if ( flo >= exc ) { //A nonsaturating push.
jacint@451
   439
	      
jacint@451
   440
	      flow->set(e, flo-exc);
jacint@451
   441
	      excess.set(v, excess[v]+exc);
jacint@451
   442
	      exc=0;
jacint@451
   443
	      break; 
jacint@451
   444
	    } else {  //A saturating push.
jacint@451
   445
	      
jacint@451
   446
	      excess.set(v, excess[v]+flo);
jacint@451
   447
	      exc-=flo;
jacint@451
   448
	      flow->set(e,0);
jacint@451
   449
	    }  
jacint@451
   450
	  } else if ( newlevel > level[v] ) newlevel = level[v];
jacint@451
   451
	} //for in edges vw
jacint@451
   452
	
jacint@451
   453
      } // if w still has excess after the out edge for cycle
jacint@451
   454
      
jacint@451
   455
      excess.set(w, exc);
jacint@451
   456
      
jacint@451
   457
      return newlevel;
jacint@451
   458
     }
jacint@451
   459
jacint@451
   460
jacint@451
   461
    void preflowPreproc ( flowEnum fe, VecStack& active, 
jacint@451
   462
			  VecNode& level_list, NNMap& left, NNMap& right ) {
jacint@451
   463
jacint@451
   464
      std::queue<Node> bfs_queue;
jacint@451
   465
      
jacint@451
   466
      switch ( fe ) {
jacint@451
   467
      case ZERO_FLOW: 
jacint@451
   468
	{
jacint@451
   469
	  //Reverse_bfs from t, to find the starting level.
jacint@451
   470
	  level.set(t,0);
jacint@451
   471
	  bfs_queue.push(t);
jacint@451
   472
	
jacint@451
   473
	  while (!bfs_queue.empty()) {
jacint@451
   474
	    
jacint@451
   475
	    Node v=bfs_queue.front();	
jacint@451
   476
	    bfs_queue.pop();
jacint@451
   477
	    int l=level[v]+1;
jacint@451
   478
	    
jacint@451
   479
	    InEdgeIt e;
marci@466
   480
	    for(g->first(e,v); g->valid(e); g->next(e)) {
marci@466
   481
	      Node w=g->tail(e);
jacint@451
   482
	      if ( level[w] == n && w != s ) {
jacint@451
   483
		bfs_queue.push(w);
jacint@451
   484
		Node first=level_list[l];
marci@466
   485
		if ( g->valid(first) ) left.set(first,w);
jacint@451
   486
		right.set(w,first);
jacint@451
   487
		level_list[l]=w;
jacint@451
   488
		level.set(w, l);
jacint@451
   489
	      }
jacint@451
   490
	    }
jacint@451
   491
	  }
jacint@451
   492
	  
jacint@451
   493
	  //the starting flow
jacint@451
   494
	  OutEdgeIt e;
marci@466
   495
	  for(g->first(e,s); g->valid(e); g->next(e)) 
jacint@451
   496
	    {
jacint@451
   497
	      T c=(*capacity)[e];
jacint@451
   498
	      if ( c == 0 ) continue;
marci@466
   499
	      Node w=g->head(e);
jacint@451
   500
	      if ( level[w] < n ) {	  
jacint@451
   501
		if ( excess[w] == 0 && w!=t ) active[level[w]].push(w);
jacint@451
   502
		flow->set(e, c); 
jacint@451
   503
		excess.set(w, excess[w]+c);
jacint@451
   504
	      }
jacint@451
   505
	    }
jacint@451
   506
	  break;
jacint@451
   507
	}
jacint@451
   508
	
jacint@451
   509
      case GEN_FLOW:
jacint@451
   510
      case PREFLOW:
jacint@451
   511
	{
jacint@451
   512
	  //Reverse_bfs from t in the residual graph, 
jacint@451
   513
	  //to find the starting level.
jacint@451
   514
	  level.set(t,0);
jacint@451
   515
	  bfs_queue.push(t);
jacint@451
   516
	  
jacint@451
   517
	  while (!bfs_queue.empty()) {
jacint@451
   518
	    
jacint@451
   519
	    Node v=bfs_queue.front();	
jacint@451
   520
	    bfs_queue.pop();
jacint@451
   521
	    int l=level[v]+1;
jacint@451
   522
	    
jacint@451
   523
	    InEdgeIt e;
marci@466
   524
	    for(g->first(e,v); g->valid(e); g->next(e)) {
jacint@451
   525
	      if ( (*capacity)[e] == (*flow)[e] ) continue;
marci@466
   526
	      Node w=g->tail(e);
jacint@451
   527
	      if ( level[w] == n && w != s ) {
jacint@451
   528
		bfs_queue.push(w);
jacint@451
   529
		Node first=level_list[l];
marci@466
   530
		if ( g->valid(first) ) left.set(first,w);
jacint@451
   531
		right.set(w,first);
jacint@451
   532
		level_list[l]=w;
jacint@451
   533
		level.set(w, l);
jacint@451
   534
	      }
jacint@451
   535
	    }
jacint@451
   536
	    
jacint@451
   537
	    OutEdgeIt f;
marci@466
   538
	    for(g->first(f,v); g->valid(f); g->next(f)) {
jacint@451
   539
	      if ( 0 == (*flow)[f] ) continue;
marci@466
   540
	      Node w=g->head(f);
jacint@451
   541
	      if ( level[w] == n && w != s ) {
jacint@451
   542
		bfs_queue.push(w);
jacint@451
   543
		Node first=level_list[l];
marci@466
   544
		if ( g->valid(first) ) left.set(first,w);
jacint@451
   545
		right.set(w,first);
jacint@451
   546
		level_list[l]=w;
jacint@451
   547
		level.set(w, l);
jacint@451
   548
	      }
jacint@451
   549
	    }
jacint@451
   550
	  }
jacint@451
   551
	  
jacint@451
   552
	  
jacint@451
   553
	  //the starting flow
jacint@451
   554
	  OutEdgeIt e;
marci@466
   555
	  for(g->first(e,s); g->valid(e); g->next(e)) 
jacint@451
   556
	    {
jacint@451
   557
	      T rem=(*capacity)[e]-(*flow)[e];
jacint@451
   558
	      if ( rem == 0 ) continue;
marci@466
   559
	      Node w=g->head(e);
jacint@451
   560
	      if ( level[w] < n ) {	  
jacint@451
   561
		if ( excess[w] == 0 && w!=t ) active[level[w]].push(w);
jacint@451
   562
		flow->set(e, (*capacity)[e]); 
jacint@451
   563
		excess.set(w, excess[w]+rem);
jacint@451
   564
	      }
jacint@451
   565
	    }
jacint@451
   566
	  
jacint@451
   567
	  InEdgeIt f;
marci@466
   568
	  for(g->first(f,s); g->valid(f); g->next(f)) 
jacint@451
   569
	    {
jacint@451
   570
	      if ( (*flow)[f] == 0 ) continue;
marci@466
   571
	      Node w=g->tail(f);
jacint@451
   572
	      if ( level[w] < n ) {	  
jacint@451
   573
		if ( excess[w] == 0 && w!=t ) active[level[w]].push(w);
jacint@451
   574
		excess.set(w, excess[w]+(*flow)[f]);
jacint@451
   575
		flow->set(f, 0); 
jacint@451
   576
	      }
jacint@451
   577
	    }  
jacint@451
   578
	  break;
jacint@451
   579
	} //case PREFLOW
jacint@451
   580
      }
jacint@451
   581
    } //preflowPreproc
jacint@451
   582
jacint@451
   583
jacint@451
   584
jacint@451
   585
    void relabel( const Node w, int newlevel, VecStack& active,  
jacint@451
   586
		  VecNode& level_list, NNMap& left, 
jacint@451
   587
		  NNMap& right, int& b, int& k, const bool what_heur ) {
jacint@451
   588
jacint@451
   589
      T lev=level[w];	
jacint@451
   590
      
jacint@451
   591
      Node right_n=right[w];
jacint@451
   592
      Node left_n=left[w];
jacint@451
   593
      
jacint@451
   594
      //unlacing starts
marci@466
   595
      if ( g->valid(right_n) ) {
marci@466
   596
	if ( g->valid(left_n) ) {
jacint@451
   597
	  right.set(left_n, right_n);
jacint@451
   598
	  left.set(right_n, left_n);
jacint@451
   599
	} else {
jacint@451
   600
	  level_list[lev]=right_n;   
jacint@451
   601
	  left.set(right_n, INVALID);
jacint@451
   602
	} 
jacint@451
   603
      } else {
marci@466
   604
	if ( g->valid(left_n) ) {
jacint@451
   605
	  right.set(left_n, INVALID);
jacint@451
   606
	} else { 
jacint@451
   607
	  level_list[lev]=INVALID;   
jacint@451
   608
	} 
jacint@451
   609
      } 
jacint@451
   610
      //unlacing ends
jacint@451
   611
		
marci@466
   612
      if ( !g->valid(level_list[lev]) ) {
jacint@451
   613
	      
jacint@451
   614
	//gapping starts
jacint@451
   615
	for (int i=lev; i!=k ; ) {
jacint@451
   616
	  Node v=level_list[++i];
marci@466
   617
	  while ( g->valid(v) ) {
jacint@451
   618
	    level.set(v,n);
jacint@451
   619
	    v=right[v];
jacint@451
   620
	  }
jacint@451
   621
	  level_list[i]=INVALID;
jacint@451
   622
	  if ( !what_heur ) {
jacint@451
   623
	    while ( !active[i].empty() ) {
jacint@451
   624
	      active[i].pop();    //FIXME: ezt szebben kene
jacint@451
   625
	    }
jacint@451
   626
	  }	     
jacint@451
   627
	}
jacint@451
   628
	
jacint@451
   629
	level.set(w,n);
jacint@451
   630
	b=lev-1;
jacint@451
   631
	k=b;
jacint@451
   632
	//gapping ends
jacint@451
   633
	
jacint@451
   634
      } else {
jacint@451
   635
	
jacint@451
   636
	if ( newlevel == n ) level.set(w,n); 
jacint@451
   637
	else {
jacint@451
   638
	  level.set(w,++newlevel);
jacint@451
   639
	  active[newlevel].push(w);
jacint@451
   640
	  if ( what_heur ) b=newlevel;
jacint@451
   641
	  if ( k < newlevel ) ++k;      //now k=newlevel
jacint@451
   642
	  Node first=level_list[newlevel];
marci@466
   643
	  if ( g->valid(first) ) left.set(first,w);
jacint@451
   644
	  right.set(w,first);
jacint@451
   645
	  left.set(w,INVALID);
jacint@451
   646
	  level_list[newlevel]=w;
jacint@451
   647
	}
jacint@451
   648
      }
jacint@451
   649
      
jacint@451
   650
    } //relabel
jacint@451
   651
    
jacint@109
   652
jacint@109
   653
  };
jacint@109
   654
marci@174
   655
} //namespace hugo
jacint@109
   656
jacint@451
   657
#endif //HUGO_PREFLOW_H
jacint@109
   658
jacint@109
   659
marci@174
   660
marci@174
   661