#ifndef EDMONDS_KARP_HH #define EDMONDS_KARP_HH #include #include #include #include namespace marci { template class ResGraph { typedef typename Graph::NodeIt NodeIt; typedef typename Graph::EachNodeIt EachNodeIt; typedef typename Graph::SymEdgeIt OldSymEdgeIt; const Graph& G; FlowMap& flow; const CapacityMap& capacity; public: ResGraph(const Graph& _G, FlowMap& _flow, const CapacityMap& _capacity) : G(_G), flow(_flow), capacity(_capacity) { } class EdgeIt; class OutEdgeIt; friend class EdgeIt; friend class OutEdgeIt; class EdgeIt { friend class ResGraph; protected: const ResGraph* resG; OldSymEdgeIt sym; public: EdgeIt() { } //EdgeIt(const EdgeIt& e) : resG(e.resG), sym(e.sym) { } Number free() const { if (resG->G.aNode(sym)==resG->G.tail(sym)) { return (resG->capacity.get(sym)-resG->flow.get(sym)); } else { return (resG->flow.get(sym)); } } bool valid() const { return sym.valid(); } void augment(Number a) const { if (resG->G.aNode(sym)==resG->G.tail(sym)) { resG->flow.set(sym, resG->flow.get(sym)+a); //resG->flow[sym]+=a; } else { resG->flow.set(sym, resG->flow.get(sym)-a); //resG->flow[sym]-=a; } } }; class OutEdgeIt : public EdgeIt { friend class ResGraph; public: OutEdgeIt() { } //OutEdgeIt(const OutEdgeIt& e) { resG=e.resG; sym=e.sym; } private: OutEdgeIt(const ResGraph& _resG, NodeIt v) { resG=&_resG; sym=resG->G.template first(v); while( sym.valid() && !(free()>0) ) { ++sym; } } public: OutEdgeIt& operator++() { ++sym; while( sym.valid() && !(free()>0) ) { ++sym; } return *this; } }; void getFirst(OutEdgeIt& e, NodeIt v) const { e=OutEdgeIt(*this, v); } void getFirst(EachNodeIt& v) const { G.getFirst(v); } template< typename It > It first() const { It e; getFirst(e); return e; } template< typename It > It first(NodeIt v) const { It e; getFirst(e, v); return e; } NodeIt tail(EdgeIt e) const { return G.aNode(e.sym); } NodeIt head(EdgeIt e) const { return G.bNode(e.sym); } NodeIt aNode(OutEdgeIt e) const { return G.aNode(e.sym); } NodeIt bNode(OutEdgeIt e) const { return G.bNode(e.sym); } int id(NodeIt v) const { return G.id(v); } template class NodeMap { typename Graph::NodeMap node_map; public: NodeMap(const ResGraph& _G) : node_map(_G.G) { } NodeMap(const ResGraph& _G, S a) : node_map(_G.G, a) { } void set(NodeIt nit, S a) { node_map.set(nit, a); } S get(NodeIt nit) const { return node_map.get(nit); } S& operator[](NodeIt nit) { return node_map[nit]; } const S& operator[](NodeIt nit) const { return node_map[nit]; } }; }; template class ResGraph2 { typedef typename Graph::NodeIt NodeIt; typedef typename Graph::EachNodeIt EachNodeIt; //typedef typename Graph::SymEdgeIt OldSymEdgeIt; typedef typename Graph::OutEdgeIt OldOutEdgeIt; typedef typename Graph::InEdgeIt OldInEdgeIt; const Graph& G; FlowMap& flow; const CapacityMap& capacity; public: ResGraph2(const Graph& _G, FlowMap& _flow, const CapacityMap& _capacity) : G(_G), flow(_flow), capacity(_capacity) { } class EdgeIt; class OutEdgeIt; friend class EdgeIt; friend class OutEdgeIt; class EdgeIt { friend class ResGraph2; protected: const ResGraph2* resG; //OldSymEdgeIt sym; OldOutEdgeIt out; OldInEdgeIt in; bool out_or_in; //1, iff out public: EdgeIt() : out_or_in(1) { } Number free() const { if (out_or_in) { return (resG->capacity.get(out)-resG->flow.get(out)); } else { return (resG->flow.get(in)); } } bool valid() const { return out_or_in && out.valid() || in.valid(); } void augment(Number a) const { if (out_or_in) { resG->flow.set(out, resG->flow.get(out)+a); } else { resG->flow.set(in, resG->flow.get(in)-a); } } }; class OutEdgeIt : public EdgeIt { friend class ResGraph2; public: OutEdgeIt() { } private: OutEdgeIt(const ResGraph2& _resG, NodeIt v) { resG=&_resG; out=resG->G.template first(v); while( out.valid() && !(free()>0) ) { ++out; } if (!out.valid()) { out_or_in=0; in=resG->G.template first(v); while( in.valid() && !(free()>0) ) { ++in; } } } public: OutEdgeIt& operator++() { if (out_or_in) { NodeIt v=resG->G.aNode(out); ++out; while( out.valid() && !(free()>0) ) { ++out; } if (!out.valid()) { out_or_in=0; in=resG->G.template first(v); while( in.valid() && !(free()>0) ) { ++in; } } } else { ++in; while( in.valid() && !(free()>0) ) { ++in; } } return *this; } }; void getFirst(OutEdgeIt& e, NodeIt v) const { e=OutEdgeIt(*this, v); } void getFirst(EachNodeIt& v) const { G.getFirst(v); } template< typename It > It first() const { It e; getFirst(e); return e; } template< typename It > It first(NodeIt v) const { It e; getFirst(e, v); return e; } NodeIt tail(EdgeIt e) const { return ((e.out_or_in) ? G.aNode(e.out) : G.aNode(e.in)); } NodeIt head(EdgeIt e) const { return ((e.out_or_in) ? G.bNode(e.out) : G.bNode(e.in)); } NodeIt aNode(OutEdgeIt e) const { return ((e.out_or_in) ? G.aNode(e.out) : G.aNode(e.in)); } NodeIt bNode(OutEdgeIt e) const { return ((e.out_or_in) ? G.bNode(e.out) : G.bNode(e.in)); } int id(NodeIt v) const { return G.id(v); } template class NodeMap { typename Graph::NodeMap node_map; public: NodeMap(const ResGraph2& _G) : node_map(_G.G) { } NodeMap(const ResGraph2& _G, S a) : node_map(_G.G, a) { } void set(NodeIt nit, S a) { node_map.set(nit, a); } S get(NodeIt nit) const { return node_map.get(nit); } }; }; template class ResGraph3 { typedef typename Graph::NodeIt NodeIt; typedef typename Graph::EachNodeIt EachNodeIt; //typedef typename Graph::SymEdgeIt OldSymEdgeIt; typedef typename Graph::OutEdgeIt OldOutEdgeIt; typedef typename Graph::InEdgeIt OldInEdgeIt; const Graph& G; FlowMap& flow; const CapacityMap& capacity; public: ResGraph3(const Graph& _G, FlowMap& _flow, const CapacityMap& _capacity) : G(_G), flow(_flow), capacity(_capacity) { } class EdgeIt; class OutEdgeIt; friend class EdgeIt; friend class OutEdgeIt; class EdgeIt { friend class ResGraph3; protected: //const ResGraph3* resG; const Graph* G; FlowMap* flow; const CapacityMap* capacity; //OldSymEdgeIt sym; OldOutEdgeIt out; OldInEdgeIt in; bool out_or_in; //1, iff out public: EdgeIt() : out_or_in(1) { } Number free() const { if (out_or_in) { return (/*resG->*/capacity->get(out)-/*resG->*/flow->get(out)); } else { return (/*resG->*/flow->get(in)); } } bool valid() const { return out_or_in && out.valid() || in.valid(); } void augment(Number a) const { if (out_or_in) { /*resG->*/flow->set(out, /*resG->*/flow->get(out)+a); } else { /*resG->*/flow->set(in, /*resG->*/flow->get(in)-a); } } }; class OutEdgeIt : public EdgeIt { friend class ResGraph3; public: OutEdgeIt() { } private: OutEdgeIt(const Graph& _G, NodeIt v, FlowMap& _flow, const CapacityMap& _capacity) { G=&_G; flow=&_flow; capacity=&_capacity; out=/*resG->*/G->template first(v); while( out.valid() && !(free()>0) ) { ++out; } if (!out.valid()) { out_or_in=0; in=/*resG->*/G->template first(v); while( in.valid() && !(free()>0) ) { ++in; } } } public: OutEdgeIt& operator++() { if (out_or_in) { NodeIt v=/*resG->*/G->aNode(out); ++out; while( out.valid() && !(free()>0) ) { ++out; } if (!out.valid()) { out_or_in=0; in=/*resG->*/G->template first(v); while( in.valid() && !(free()>0) ) { ++in; } } } else { ++in; while( in.valid() && !(free()>0) ) { ++in; } } return *this; } }; void getFirst(OutEdgeIt& e, NodeIt v) const { e=OutEdgeIt(G, v, flow, capacity); } void getFirst(EachNodeIt& v) const { G.getFirst(v); } template< typename It > It first() const { It e; getFirst(e); return e; } template< typename It > It first(NodeIt v) const { It e; getFirst(e, v); return e; } NodeIt tail(EdgeIt e) const { return ((e.out_or_in) ? G.aNode(e.out) : G.aNode(e.in)); } NodeIt head(EdgeIt e) const { return ((e.out_or_in) ? G.bNode(e.out) : G.bNode(e.in)); } NodeIt aNode(OutEdgeIt e) const { return ((e.out_or_in) ? G.aNode(e.out) : G.aNode(e.in)); } NodeIt bNode(OutEdgeIt e) const { return ((e.out_or_in) ? G.bNode(e.out) : G.bNode(e.in)); } int id(NodeIt v) const { return G.id(v); } template class NodeMap { typename Graph::NodeMap node_map; public: NodeMap(const ResGraph3& _G) : node_map(_G.G) { } NodeMap(const ResGraph3& _G, S a) : node_map(_G.G, a) { } void set(NodeIt nit, S a) { node_map.set(nit, a); } S get(NodeIt nit) const { return node_map.get(nit); } }; }; template class MaxFlow { typedef typename Graph::NodeIt NodeIt; typedef typename Graph::EdgeIt EdgeIt; typedef typename Graph::EachEdgeIt EachEdgeIt; typedef typename Graph::OutEdgeIt OutEdgeIt; typedef typename Graph::InEdgeIt InEdgeIt; const Graph& G; NodeIt s; NodeIt t; FlowMap& flow; const CapacityMap& capacity; typedef ResGraph3 AugGraph; typedef typename AugGraph::OutEdgeIt AugOutEdgeIt; typedef typename AugGraph::EdgeIt AugEdgeIt; //AugGraph res_graph; //typedef typename AugGraph::NodeMap ReachedMap; //typename AugGraph::NodeMap pred; //typename AugGraph::NodeMap free; public: MaxFlow(const Graph& _G, NodeIt _s, NodeIt _t, FlowMap& _flow, const CapacityMap& _capacity) : G(_G), s(_s), t(_t), flow(_flow), capacity(_capacity) //, //res_graph(G, flow, capacity), pred(res_graph), free(res_graph) { } bool augment() { AugGraph res_graph(G, flow, capacity); bool _augment=false; typedef typename AugGraph::NodeMap ReachedMap; BfsIterator4< AugGraph, AugOutEdgeIt, ReachedMap > res_bfs(res_graph); res_bfs.pushAndSetReached(s); typename AugGraph::NodeMap pred(res_graph); //filled up with invalid iterators //pred.set(s, AugEdgeIt()); typename AugGraph::NodeMap free(res_graph); //searching for augmenting path while ( !res_bfs.finished() ) { AugOutEdgeIt e=AugOutEdgeIt(res_bfs); if (e.valid() && res_bfs.isBNodeNewlyReached()) { NodeIt v=res_graph.tail(e); NodeIt w=res_graph.head(e); pred.set(w, e); if (pred.get(v).valid()) { free.set(w, std::min(free.get(v), e.free())); } else { free.set(w, e.free()); } if (res_graph.head(e)==t) { _augment=true; break; } } ++res_bfs; } //end of searching augmenting path if (_augment) { NodeIt n=t; Number augment_value=free.get(t); while (pred.get(n).valid()) { AugEdgeIt e=pred.get(n); e.augment(augment_value); n=res_graph.tail(e); } } return _augment; } void run() { while (augment()) { } } Number flowValue() { Number a=0; for(OutEdgeIt i=G.template first(s); i.valid(); ++i) { a+=flow.get(i); } return a; } }; /* template class IteratorBoolNodeMap { typedef typename Graph::NodeIt NodeIt; typedef typename Graph::EachNodeIt EachNodeIt; class BoolItem { public: bool value; NodeIt prev; NodeIt next; BoolItem() : value(false), prev(), next() {} }; NodeIt first_true; //NodeIt last_true; NodeIt first_false; //NodeIt last_false; const Graph& G; typename Graph::NodeMap container; public: typedef bool ValueType; typedef NodeIt KeyType; IteratorBoolNodeMap(const Graph& _G) : G(_G), container(G), first_true(NodeIt()) { //for (EachNodeIt e=G.template first(); e.valid(); ++e) { //BoolItem b=container.get(e); //b.me=e; //container.set(b); //} G.getFirst(first_false); NodeIt e_prev; for (EachNodeIt e=G.template first(); e.valid(); ++e) { container[e].prev=e_prev; if (e_prev.valid()) container[e_prev].next=e; e_prev=e; } } //NodeMap(const Graph& _G, T a) : // G(_G), container(G.node_id, a) { } //FIXME void set(NodeIt nit, T a) { container[G.id(nit)]=a; } T get(NodeIt nit) const { return container[G.id(nit)]; } //void resize() { container.resize(G.node_id); } //void resize(T a) { container.resize(G.node_id, a); } }; */ template class MaxFlow2 { typedef typename Graph::NodeIt NodeIt; typedef typename Graph::EdgeIt EdgeIt; typedef typename Graph::EachEdgeIt EachEdgeIt; typedef typename Graph::OutEdgeIt OutEdgeIt; typedef typename Graph::InEdgeIt InEdgeIt; const Graph& G; std::list& S; std::list& T; FlowMap& flow; const CapacityMap& capacity; typedef ResGraph AugGraph; typedef typename AugGraph::OutEdgeIt AugOutEdgeIt; typedef typename AugGraph::EdgeIt AugEdgeIt; typename Graph::NodeMap SMap; typename Graph::NodeMap TMap; public: MaxFlow2(const Graph& _G, std::list& _S, std::list& _T, FlowMap& _flow, const CapacityMap& _capacity) : G(_G), S(_S), T(_T), flow(_flow), capacity(_capacity), SMap(_G), TMap(_G) { for(typename std::list::const_iterator i=S.begin(); i!=S.end(); ++i) { SMap.set(*i, true); } for (typename std::list::const_iterator i=T.begin(); i!=T.end(); ++i) { TMap.set(*i, true); } } bool augment() { AugGraph res_graph(G, flow, capacity); bool _augment=false; NodeIt reached_t_node; typedef typename AugGraph::NodeMap ReachedMap; BfsIterator4< AugGraph, AugOutEdgeIt, ReachedMap > res_bfs(res_graph); for(typename std::list::const_iterator i=S.begin(); i!=S.end(); ++i) { res_bfs.pushAndSetReached(*i); } //res_bfs.pushAndSetReached(s); typename AugGraph::NodeMap pred(res_graph); //filled up with invalid iterators typename AugGraph::NodeMap free(res_graph); //searching for augmenting path while ( !res_bfs.finished() ) { AugOutEdgeIt e=AugOutEdgeIt(res_bfs); if (e.valid() && res_bfs.isBNodeNewlyReached()) { NodeIt v=res_graph.tail(e); NodeIt w=res_graph.head(e); pred.set(w, e); if (pred.get(v).valid()) { free.set(w, std::min(free.get(v), e.free())); } else { free.set(w, e.free()); } if (TMap.get(res_graph.head(e))) { _augment=true; reached_t_node=res_graph.head(e); break; } } ++res_bfs; } //end of searching augmenting path if (_augment) { NodeIt n=reached_t_node; Number augment_value=free.get(reached_t_node); while (pred.get(n).valid()) { AugEdgeIt e=pred.get(n); e.augment(augment_value); n=res_graph.tail(e); } } return _augment; } void run() { while (augment()) { } } Number flowValue() { Number a=0; for(typename std::list::const_iterator i=S.begin(); i!=S.end(); ++i) { for(OutEdgeIt e=G.template first(*i); e.valid(); ++e) { a+=flow.get(e); } for(InEdgeIt e=G.template first(*i); e.valid(); ++e) { a-=flow.get(e); } } return a; } }; } // namespace marci #endif //EDMONDS_KARP_HH