src/work/alpar/f_ed_ka.h
author deba
Wed, 08 Sep 2004 12:06:45 +0000
changeset 822 88226d9fe821
parent 95 3322fbf254d2
child 921 818510fa3d99
permissions -rw-r--r--
The MapFactories have been removed from the code because
if we use macros then they increases only the complexity.

The pair iterators of the maps are separeted from the maps.

Some macros and comments has been changed.
alpar@74
     1
// -*- mode:c++ -*-
alpar@74
     2
alpar@74
     3
#ifndef EDMONDS_KARP_HH
alpar@74
     4
#define EDMONDS_KARP_HH
alpar@74
     5
alpar@74
     6
#include <queue>
alpar@74
     7
alpar@74
     8
//#include <marci_property_vector.hh>
alpar@74
     9
alpar@74
    10
#include <algorithm>
alpar@74
    11
alpar@74
    12
//#include <bfs_iterator.hh>
alpar@74
    13
alpar@108
    14
namespace hugo {
alpar@74
    15
  template <typename Graph, typename FlowMap, typename CapacityMap>
alpar@74
    16
  typename FlowMap::ValueType maxFlow(Graph &G,
alpar@74
    17
				      FlowMap &f,
alpar@74
    18
				      CapacityMap &c,
marci@95
    19
				      typename Graph::NodeIt s,
marci@95
    20
				      typename Graph::NodeIt t)
alpar@74
    21
  { 
alpar@93
    22
    typedef typename Graph::NodeIt NodeIt;
alpar@91
    23
    typedef typename Graph::EachNodeIt EachNodeIt;
alpar@74
    24
    typedef typename Graph::EdgeIt EdgeIt;
alpar@74
    25
    typedef typename Graph::EachEdgeIt EachEdgeIt;
alpar@74
    26
    typedef typename Graph::OutEdgeIt OutEdgeIt;
alpar@74
    27
    typedef typename Graph::InEdgeIt InEdgeIt;
alpar@74
    28
    typedef typename FlowMap::ValueType T;
alpar@74
    29
    
alpar@74
    30
    T flow_val = 0;
alpar@74
    31
    T aug_val;
alpar@74
    32
alpar@93
    33
    for(EachEdgeIt e(G);G.valid(e);G.goNext(e))
alpar@74
    34
      f.set(e,0);
alpar@74
    35
    
alpar@93
    36
    std::queue<NodeIt> bfs_queue;
alpar@74
    37
    typename Graph::NodeMap<int> visited(G); //0: unvisited,
alpar@74
    38
                                             //1: reached by a forward edge
alpar@74
    39
                                             //2: reached by a backward edge
alpar@74
    40
                                             //3: it is node s
alpar@74
    41
    typename Graph::NodeMap<EdgeIt> tree(G);
alpar@74
    42
    
alpar@94
    43
    NodeIt gn;  //FIXME: it might be too global for some people...
alpar@74
    44
    
alpar@74
    45
  augment:
alpar@74
    46
    
alpar@93
    47
    for(EachNodeIt n(G);G.valid(n);G.goNext(n))
alpar@74
    48
      visited.set(n,0);
alpar@74
    49
    
alpar@74
    50
    visited.set(s,3);
alpar@74
    51
    
alpar@74
    52
    //There must be a better way to do this:
alpar@74
    53
    while(!bfs_queue.empty()) bfs_queue.pop();
alpar@74
    54
    
alpar@74
    55
    bfs_queue.push(s);
alpar@74
    56
    
alpar@74
    57
    while(!bfs_queue.empty() && !visited.get(t))
alpar@74
    58
      {
alpar@93
    59
	NodeIt n(bfs_queue.front());
alpar@93
    60
	bfs_queue.pop();
alpar@93
    61
	for(OutEdgeIt e(G,n);G.valid(e);G.goNext(e))
alpar@74
    62
	  if(f.get(e)<c.get(e) &&   //FIXME: <
alpar@74
    63
	     !visited.get(G.bNode(e))) 
alpar@74
    64
	    {
alpar@93
    65
	      NodeIt nn(G.bNode(e)); //It improves nothing
alpar@93
    66
	      tree.set(nn,e);
alpar@93
    67
	      visited.set(nn,1);
alpar@93
    68
	      bfs_queue.push(nn);
alpar@74
    69
	    }
alpar@93
    70
	for(InEdgeIt e(G,n);G.valid(e);G.goNext(e))
alpar@74
    71
	  if(f.get(e)>0 &&   //FIXME: >
alpar@74
    72
	     !visited.get(G.bNode(e))) 
alpar@74
    73
	    {
alpar@93
    74
	      NodeIt nn(G.bNode(e));
alpar@93
    75
	      tree.set(nn,e);
alpar@93
    76
	      visited.set(nn,2);
alpar@93
    77
	      bfs_queue.push(nn);
alpar@74
    78
	    }
alpar@74
    79
      }
alpar@74
    80
    
alpar@74
    81
    if(!visited.get(t)) return flow_val;
alpar@74
    82
alpar@74
    83
    // Augmenting value computation
alpar@80
    84
    aug_val = visited.get(t)==1 ?
alpar@74
    85
      c.get(tree.get(t))-f.get(tree.get(t)) : f.get(tree.get(t));
alpar@74
    86
    //FIXME: I would need 'G.opposite(e,n)'
alpar@80
    87
    gn = visited.get(t)==1 ? G.tail(tree.get(t)) : G.head(tree.get(t));
alpar@80
    88
    while(gn!=s) if(visited.get(gn)==1)
alpar@74
    89
      {
alpar@93
    90
	//FIXME: nonstandard gcc extension!
alpar@74
    91
	aug_val <?= c.get(tree.get(gn))-f.get(tree.get(gn));
alpar@80
    92
	gn=G.tail(tree.get(gn));
alpar@74
    93
      }
alpar@74
    94
    else {
alpar@93
    95
      //FIXME: nonstandard gcc extension!
alpar@74
    96
      aug_val <?= f.get(tree.get(gn));
alpar@80
    97
      gn=G.head(tree.get(gn));
alpar@74
    98
    }
alpar@74
    99
	
alpar@74
   100
    // The augmentation itself
alpar@74
   101
    gn = t;
alpar@80
   102
    while(gn!=s) if(visited.get(gn)==1)
alpar@74
   103
      {
alpar@74
   104
	f.set(tree.get(gn),f.get(tree.get(gn))+aug_val);
alpar@80
   105
	gn=G.tail(tree.get(gn));
alpar@74
   106
      }
alpar@74
   107
    else {
alpar@74
   108
      f.set(tree.get(gn),f.get(tree.get(gn))-aug_val);
alpar@80
   109
      gn=G.head(tree.get(gn));
alpar@74
   110
    }
alpar@74
   111
alpar@74
   112
    flow_val+=aug_val;
alpar@74
   113
alpar@74
   114
    goto augment;   // Vivat goto forever!
alpar@74
   115
  }
alpar@74
   116
  
alpar@108
   117
} // namespace hugo
alpar@74
   118
alpar@74
   119
#endif //EDMONDS_KARP_HH