src/work/edmonds_karp.hh
author alpar
Mon, 16 Feb 2004 10:57:01 +0000
changeset 74 82d3dbe912d9
parent 64 72bd463289a9
child 75 87623302a68f
permissions -rw-r--r--
.
marci@59
     1
#ifndef EDMONDS_KARP_HH
marci@59
     2
#define EDMONDS_KARP_HH
marci@43
     3
marci@43
     4
#include <algorithm>
marci@43
     5
marci@43
     6
#include <bfs_iterator.hh>
marci@43
     7
marci@43
     8
namespace marci {
marci@43
     9
marci@59
    10
  template<typename Graph, typename T, typename FlowMap, typename CapacityMap>
marci@43
    11
  class ResGraph {
marci@43
    12
    typedef typename Graph::NodeIt NodeIt;
marci@43
    13
    typedef typename Graph::EachNodeIt EachNodeIt;
marci@43
    14
    typedef typename Graph::SymEdgeIt OldSymEdgeIt;
marci@43
    15
    const Graph& G;
marci@59
    16
    FlowMap& flow;
marci@59
    17
    const CapacityMap& capacity;
marci@43
    18
  public:
marci@59
    19
    ResGraph(const Graph& _G, FlowMap& _flow, 
marci@59
    20
	     const CapacityMap& _capacity) : 
marci@43
    21
      G(_G), flow(_flow), capacity(_capacity) { }
marci@43
    22
marci@43
    23
    class EdgeIt; 
marci@43
    24
    class OutEdgeIt; 
marci@43
    25
    friend class EdgeIt; 
marci@43
    26
    friend class OutEdgeIt; 
marci@43
    27
marci@43
    28
    class EdgeIt {
marci@59
    29
      friend class ResGraph<Graph, T, FlowMap, CapacityMap>;
marci@43
    30
    protected:
marci@59
    31
      const ResGraph<Graph, T, FlowMap, CapacityMap>* resG;
marci@43
    32
      OldSymEdgeIt sym;
marci@43
    33
    public:
marci@43
    34
      EdgeIt() { } 
marci@43
    35
      //EdgeIt(const EdgeIt& e) : resG(e.resG), sym(e.sym) { }
marci@43
    36
      T free() const { 
marci@43
    37
	if (resG->G.aNode(sym)==resG->G.tail(sym)) { 
marci@43
    38
	  return (resG->capacity.get(sym)-resG->flow.get(sym)); 
marci@43
    39
	} else { 
marci@43
    40
	  return (resG->flow.get(sym)); 
marci@43
    41
	}
marci@43
    42
      }
marci@43
    43
      bool valid() const { return sym.valid(); }
marci@64
    44
      void augment(T a) const {
marci@43
    45
	if (resG->G.aNode(sym)==resG->G.tail(sym)) { 
marci@43
    46
	  resG->flow.set(sym, resG->flow.get(sym)+a);
marci@43
    47
	} else { 
marci@43
    48
	  resG->flow.set(sym, resG->flow.get(sym)-a);
marci@43
    49
	}
marci@43
    50
      }
marci@43
    51
    };
marci@43
    52
marci@43
    53
    class OutEdgeIt : public EdgeIt {
marci@59
    54
      friend class ResGraph<Graph, T, FlowMap, CapacityMap>;
marci@43
    55
    public:
marci@43
    56
      OutEdgeIt() { }
marci@43
    57
      //OutEdgeIt(const OutEdgeIt& e) { resG=e.resG; sym=e.sym; }
marci@43
    58
    private:
marci@64
    59
      OutEdgeIt(const ResGraph<Graph, T, FlowMap, CapacityMap>& _resG, NodeIt v) { 
marci@43
    60
      	resG=&_resG;
marci@43
    61
	sym=resG->G.template first<OldSymEdgeIt>(v);
marci@43
    62
	while( sym.valid() && !(free()>0) ) { ++sym; }
marci@43
    63
      }
marci@43
    64
    public:
marci@43
    65
      OutEdgeIt& operator++() { 
marci@43
    66
	++sym; 
marci@43
    67
	while( sym.valid() && !(free()>0) ) { ++sym; }
marci@43
    68
	return *this; 
marci@43
    69
      }
marci@43
    70
    };
marci@43
    71
marci@64
    72
    void getFirst(OutEdgeIt& e, NodeIt v) const { 
marci@43
    73
      e=OutEdgeIt(*this, v); 
marci@43
    74
    }
marci@43
    75
    void getFirst(EachNodeIt& v) const { G.getFirst(v); }
marci@43
    76
    
marci@43
    77
    template< typename It >
marci@43
    78
    It first() const { 
marci@43
    79
      It e;
marci@43
    80
      getFirst(e);
marci@43
    81
      return e; 
marci@43
    82
    }
marci@43
    83
marci@43
    84
    template< typename It >
marci@64
    85
    It first(NodeIt v) const { 
marci@43
    86
      It e;
marci@43
    87
      getFirst(e, v);
marci@43
    88
      return e; 
marci@43
    89
    }
marci@43
    90
marci@64
    91
    NodeIt tail(EdgeIt e) const { return G.aNode(e.sym); }
marci@64
    92
    NodeIt head(EdgeIt e) const { return G.bNode(e.sym); }
marci@43
    93
marci@64
    94
    NodeIt aNode(OutEdgeIt e) const { return G.aNode(e.sym); }
marci@64
    95
    NodeIt bNode(OutEdgeIt e) const { return G.bNode(e.sym); }
marci@43
    96
marci@64
    97
    int id(NodeIt v) const { return G.id(v); }
marci@43
    98
marci@69
    99
    template <typename S>
marci@43
   100
    class NodeMap {
marci@69
   101
      typename Graph::NodeMap<S> node_map; 
marci@43
   102
    public:
marci@59
   103
      NodeMap(const ResGraph<Graph, T, FlowMap, CapacityMap>& _G) : node_map(_G.G) { }
marci@69
   104
      NodeMap(const ResGraph<Graph, T, FlowMap, CapacityMap>& _G, S a) : node_map(_G.G, a) { }
marci@69
   105
      void set(NodeIt nit, S a) { node_map.set(nit, a); }
marci@69
   106
      S get(NodeIt nit) const { return node_map.get(nit); }
marci@43
   107
    };
marci@43
   108
marci@43
   109
  };
marci@43
   110
marci@59
   111
  template <typename Graph, typename T, typename FlowMap, typename CapacityMap>
marci@59
   112
  class MaxFlow {
marci@43
   113
    typedef typename Graph::NodeIt NodeIt;
marci@43
   114
    typedef typename Graph::EdgeIt EdgeIt;
marci@43
   115
    typedef typename Graph::EachEdgeIt EachEdgeIt;
marci@43
   116
    typedef typename Graph::OutEdgeIt OutEdgeIt;
marci@43
   117
    typedef typename Graph::InEdgeIt InEdgeIt;
marci@43
   118
    const Graph& G;
marci@64
   119
    NodeIt s;
marci@64
   120
    NodeIt t;
marci@59
   121
    FlowMap& flow;
marci@59
   122
    const CapacityMap& capacity;
marci@59
   123
    typedef ResGraph<Graph, T, FlowMap, CapacityMap > AugGraph;
marci@59
   124
    typedef typename AugGraph::OutEdgeIt AugOutEdgeIt;
marci@59
   125
    typedef typename AugGraph::EdgeIt AugEdgeIt;
marci@59
   126
  public:
marci@64
   127
    MaxFlow(const Graph& _G, NodeIt _s, NodeIt _t, FlowMap& _flow, const CapacityMap& _capacity) : G(_G), s(_s), t(_t), flow(_flow), capacity(_capacity) { }
marci@59
   128
    bool augment() {
marci@59
   129
      AugGraph res_graph(G, flow, capacity);
marci@59
   130
      bool _augment=false;
marci@59
   131
      
marci@59
   132
      typedef typename AugGraph::NodeMap<bool> ReachedMap;
marci@59
   133
      BfsIterator2< AugGraph, AugOutEdgeIt, ReachedMap > res_bfs(res_graph);
marci@59
   134
      res_bfs.pushAndSetReached(s);
marci@59
   135
	
marci@59
   136
      typename AugGraph::NodeMap<AugEdgeIt> pred(res_graph); 
marci@59
   137
      //filled with invalid iterators
marci@59
   138
      
marci@59
   139
      typename AugGraph::NodeMap<int> free(res_graph);
marci@59
   140
	
marci@59
   141
      //searching for augmenting path
marci@59
   142
      while ( !res_bfs.finished() ) { 
marci@59
   143
	AugOutEdgeIt e=AugOutEdgeIt(res_bfs);
marci@59
   144
	if (e.valid() && res_bfs.isBNodeNewlyReached()) {
marci@59
   145
	  NodeIt v=res_graph.tail(e);
marci@59
   146
	  NodeIt w=res_graph.head(e);
marci@59
   147
	  pred.set(w, e);
marci@59
   148
	  if (pred.get(v).valid()) {
marci@59
   149
	    free.set(w, std::min(free.get(v), e.free()));
marci@59
   150
	  } else {
marci@59
   151
	    free.set(w, e.free()); 
marci@59
   152
	  }
marci@59
   153
	  if (res_graph.head(e)==t) { _augment=true; break; }
marci@59
   154
	}
marci@59
   155
	
marci@59
   156
	++res_bfs;
marci@59
   157
      } //end of searching augmenting path
marci@43
   158
marci@59
   159
      if (_augment) {
marci@59
   160
	NodeIt n=t;
marci@59
   161
	T augment_value=free.get(t);
marci@59
   162
	while (pred.get(n).valid()) { 
marci@59
   163
	  AugEdgeIt e=pred.get(n);
marci@59
   164
	  e.augment(augment_value); 
marci@59
   165
	  n=res_graph.tail(e);
marci@59
   166
	}
marci@59
   167
      }
marci@59
   168
marci@59
   169
      return _augment;
marci@59
   170
    }
marci@43
   171
    void run() {
marci@59
   172
      while (augment()) { } 
marci@43
   173
    }
marci@69
   174
    T flowValue() { 
marci@69
   175
      T a=0;
marci@69
   176
      for(OutEdgeIt i=G.template first<OutEdgeIt>(s); i.valid(); ++i) {
marci@69
   177
	a+=flow.get(i);
marci@69
   178
      }
marci@69
   179
      return a;
marci@69
   180
    }
marci@43
   181
  };
marci@43
   182
marci@43
   183
} // namespace marci
marci@43
   184
marci@59
   185
#endif //EDMONDS_KARP_HH