# HG changeset patch # User jacint # Date 1077795531 0 # Node ID 9aca797b87e8c610d7485652ab77568591d7a027 # Parent 5710037832022614f666049958fd1a49c16ca27d Alpar SmartGraph-janak atirasa diff -r 571003783202 -r 9aca797b87e8 src/work/jacint/dimacs_jgraph.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/work/jacint/dimacs_jgraph.hh Thu Feb 26 11:38:51 2004 +0000 @@ -0,0 +1,61 @@ +#ifndef DIMACS_HH +#define DIMACS_HH + +#include +#include +#include + +namespace hugo { + + template + void readDimacsMaxFlow(std::istream& is, Graph &G, typename Graph::TrivNodeIt &s, typename Graph::TrivNodeIt &t, CapacityMap& capacity) { + G.clear(); + int cap; + char d; + std::string problem; + char c; + int i, j; + std::string str; + int n, m; + std::vector nodes; + while (is>>c) { + switch (c) { + case 'c': //comment + getline(is, str); + break; + case 't': //type + getline(is, str); + break; + case 'p': //problem definition + is >> problem >> n >> m; + getline(is, str); + nodes.resize(n+1); + for (int k=1; k<=n; ++k) nodes[k]=G.addNode(); + break; + case 'n': //node definition + if (problem=="sp") { //shortest path problem + is >> i; + getline(is, str); + s=nodes[i]; + } + if (problem=="max") { //max flow problem + is >> i >> d; + getline(is, str); + if (d=='s') s=nodes[i]; + if (d=='t') t=nodes[i]; + } + break; + case 'a': + is >> i >> j >> cap; + getline(is, str); + typename Graph::TrivEdgeIt e=G.addEdge(nodes[i], nodes[j]); + capacity.update(); + capacity.set(e, cap); + break; + } + } + } + +} //namespace marci + +#endif //DIMACS_HH diff -r 571003783202 -r 9aca797b87e8 src/work/jacint/j_graph.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/work/jacint/j_graph.h Thu Feb 26 11:38:51 2004 +0000 @@ -0,0 +1,363 @@ +// -*- mode:C++ -*- + +#ifndef J_GRAPH_H +#define J_GRAPH_H + +#include +#include + +namespace hugo { + + class JGraph { + + struct NodeT + { + int in, out; + NodeT() : in(), out() {} + }; + + struct EdgeT + { + int head, tail, in, out; + }; + + + std::vector nodes; + std::vector edges; + + + /* template class DynMapBase + { + protected: + SmartGraph* G; + public: + virtual void add(const Key k) = NULL; + virtual void erase(const Key k) = NULL; + DynMapBase(SmartGraph &_G) : G(&_G) {} + virtual ~DynMapBase() {} + friend class SmartGraph; + }; + + template class DynEdgeMap; + template class DynEdgeMap; + */ + + public: + + class TrivNodeIt; + class TrivEdgeIt; + class NodeIt; + class EdgeIt; + class OutEdgeIt; + class InEdgeIt; + + /* protected: + std::vector * > dyn_node_maps; + std::vector * > dyn_edge_maps; + */ + + template class NodeMap; + template class EdgeMap; + + public: + + JGraph() : nodes(1), edges(1) { + edges[0].head=0; + edges[0].tail=0; + edges[0].in=0; //numEdges (numNodes is maintained in nodes[0].in) + edges[0].out=0; + } + + + /* ~SmartGraph() + { + for(std::vector * >::iterator i=dyn_node_maps.begin(); + i!=dyn_node_maps.end(); ++i) (**i).G=NULL; + for(std::vector * >::iterator i=dyn_edge_maps.begin(); + i!=dyn_edge_maps.end(); ++i) (**i).G=NULL; + }*/ + + int numNodes() const { return nodes[0].in; } + int numEdges() const { return edges[0].in; } + + TrivNodeIt tail(TrivEdgeIt e) const { return edges[e.n].tail; } + TrivNodeIt head(TrivEdgeIt e) const { return edges[e.n].head; } + + /* EachNodeIt& getFirst(EachNodeIt& v) const { + v=EachNodeIt(*this); return v; } + EachEdgeIt& getFirst(EachEdgeIt& e) const { + e=EachEdgeIt(*this); return e; } + OutEdgeIt& getFirst(OutEdgeIt& e, const NodeIt v) const { + e=OutEdgeIt(*this,v); return e; } + InEdgeIt& getFirst(InEdgeIt& e, const NodeIt v) const { + e=InEdgeIt(*this,v); return e; } + */ + + NodeIt firstNode() const { + return NodeIt( numNodes() ); + } + EdgeIt firstEdge() const { + return EdgeIt( numEdges() ); + } + InEdgeIt firstIn(TrivNodeIt v) const { + return InEdgeIt(nodes[v.n].in); + } + OutEdgeIt firstOut(TrivNodeIt v) const { + return OutEdgeIt(nodes[v.n].out); + } + + + + void next(NodeIt& it) const {--it.n;} + void next(OutEdgeIt& it) const { it.n=edges[it.n].out; } + void next(InEdgeIt& it) const { it.n=edges[it.n].in; } + void next(EdgeIt& it) const {--it.n;} + + int id(TrivNodeIt v) const { return v.n; } + int id(TrivEdgeIt e) const { return e.n; } + + TrivNodeIt addNode() { + TrivNodeIt n; + n.n=++nodes[0].in; + nodes.push_back(NodeT()); //FIXME + + /* for(std::vector * >::iterator i=dyn_node_maps.begin(); + i!=dyn_node_maps.end(); ++i) (**i).add(n.n);*/ + + return n; + } + + + TrivEdgeIt addEdge(TrivNodeIt u, TrivNodeIt v) { + if ( u && v ) { + TrivEdgeIt e; + e.n=++edges[0].in; + edges.push_back(EdgeT()); //FIXME: Hmmm... + edges[e.n].tail=u.n; edges[e.n].head=v.n; + edges[e.n].out=nodes[u.n].out; + edges[e.n].in=nodes[v.n].in; + nodes[u.n].out=nodes[v.n].in=e.n; + return e; + } + else return TrivEdgeIt(); + + /* for(std::vector * >::iterator i=dyn_edge_maps.begin(); + i!=dyn_edge_maps.end(); ++i) (**i).add(e.n);*/ + + + } + + + void clear() { + nodes.resize(1); + edges.resize(1); edges[0].in=0; + } + + + class TrivNodeIt { + friend class JGraph; + template friend class NodeMap; + + friend class TrivEdgeIt; + friend class OutEdgeIt; + friend class InEdgeIt; + + protected: + int n; + public: + TrivNodeIt() : n() {} + TrivNodeIt(int number) {n=number;} + bool operator==(const TrivNodeIt i) const {return n==i.n;} + bool operator!=(const TrivNodeIt i) const {return n!=i.n;} + + operator bool() const { return n!=0; } + + }; + + + class NodeIt : public TrivNodeIt { + friend class JGraph; + public: + NodeIt() : TrivNodeIt() { } + NodeIt(int i) : TrivNodeIt(i) { } + operator bool() const { return n!=0; } + }; + + + class TrivEdgeIt { + friend class JGraph; + template friend class EdgeMap; + + friend class TrivNodeIt; + friend class NodeIt; + protected: + int n; + public: + TrivEdgeIt() : n() { } + TrivEdgeIt(int number) {n=number;} + bool operator==(const TrivEdgeIt i) const {return n==i.n;} + bool operator!=(const TrivEdgeIt i) const {return n!=i.n;} + operator bool() const { return n!=0; } + + }; + + + class EdgeIt : public TrivEdgeIt { + friend class JGraph; + public: + EdgeIt() : TrivEdgeIt() { } + EdgeIt(int i) : TrivEdgeIt(i) { } + operator bool() const { return n!=0; } + }; + + + class OutEdgeIt : public TrivEdgeIt { + friend class JGraph; + public: + OutEdgeIt() : TrivEdgeIt() { } + OutEdgeIt(int i) : TrivEdgeIt(i) { } + }; + + + class InEdgeIt : public TrivEdgeIt { + friend class JGraph; + public: + InEdgeIt() : TrivEdgeIt() { } + InEdgeIt(int i) : TrivEdgeIt(i) { } + }; + + + // Map types + + template + class NodeMap { + const JGraph& G; + std::vector container; + public: + NodeMap(const JGraph& _G) : G(_G), container( G.numNodes()+1 ) { } + NodeMap(const JGraph& _G, T a) : + G(_G), container(G.numNodes()+1, a) { } + void set(TrivNodeIt n, T a) { container[n.n]=a; } + T get(TrivNodeIt n) const { return container[n.n]; } + /*T& operator[](NodeIt n) { return container[n.n]; } + const T& operator[](NodeIt n) const { return container[n.n]; }*/ + void update() { container.resize(G.numNodes()+1); } + void update(T a) { container.resize(G.numNodes()+1, a); } + }; + + template + class EdgeMap { + const JGraph& G; + std::vector container; + public: + EdgeMap(const JGraph& _G) : G(_G), container(G.numEdges()+1) { } + EdgeMap(const JGraph& _G, T a) : + G(_G), container(G.numEdges()+1, a) { } + void set(TrivEdgeIt e, T a) { container[e.n]=a; } + T get(TrivEdgeIt e) const { return container[e.n]; } + /*T& operator[](EdgeIt e) { return container[e.n]; } + const T& operator[](EdgeIt e) const { return container[e.n]; } */ + void update() { container.resize(G.numEdges()+1); } + void update(T a) { container.resize(G.numEdges()+1, a); } + }; + + /*template class DynNodeMap : public DynMapBase + { + std::vector container; + + public: + typedef T ValueType; + typedef NodeIt KeyType; + + DynNodeMap(JGraph &_G) : + DynMapBase(_G), container(_G.maxNodeId()) + { + //FIXME: What if there are empty Id's? + //FIXME: Can I use 'this' in a constructor? + G->dyn_node_maps.push_back(this); + } + ~DynNodeMap() + { + if(G) { + std::vector* >::iterator i; + for(i=G->dyn_node_maps.begin(); + i!=G->dyn_node_maps.end() && *i!=this; ++i) ; + //if(*i==this) G->dyn_node_maps.erase(i); //FIXME: Way too slow... + //A better way to do that: (Is this really important?) + if(*i==this) { + *i=G->dyn_node_maps.back(); + G->dyn_node_maps.pop_back(); + } + } + } + + void add(const NodeIt k) + { + if(k.n>=container.size()) container.resize(k.n+1); + } + void erase(const NodeIt k) + { + //FIXME: Please implement me. + } + + void set(NodeIt n, T a) { container[n.n]=a; } + T get(NodeIt n) const { return container[n.n]; } + T& operator[](NodeIt n) { return container[n.n]; } + const T& operator[](NodeIt n) const { return container[n.n]; } + + void update() {} //Useless for DynMaps + void update(T a) {} //Useless for DynMaps + }; + + template class DynEdgeMap : public DynMapBase + { + std::vector container; + + public: + typedef T ValueType; + typedef EdgeIt KeyType; + + DynEdgeMap(JGraph &_G) : + DynMapBase(_G), container(_G.maxEdgeId()) + { + //FIXME: What if there are empty Id's? + //FIXME: Can I use 'this' in a constructor? + G->dyn_edge_maps.push_back(this); + } + ~DynEdgeMap() + { + if(G) { + std::vector* >::iterator i; + for(i=G->dyn_edge_maps.begin(); + i!=G->dyn_edge_maps.end() && *i!=this; ++i) ; + //if(*i==this) G->dyn_edge_maps.erase(i); //Way too slow... + //A better way to do that: (Is this really important?) + if(*i==this) { + *i=G->dyn_edge_maps.back(); + G->dyn_edge_maps.pop_back(); + } + } + } + + void add(const EdgeIt k) + { + if(k.n>=int(container.size())) container.resize(k.n+1); + } + void erase(const EdgeIt k) + { + //FIXME: Please implement me. + } + + void set(EdgeIt n, T a) { container[n.n]=a; } + T get(EdgeIt n) const { return container[n.n]; } + T& operator[](EdgeIt n) { return container[n.n]; } + const T& operator[](EdgeIt n) const { return container[n.n]; } + + void update() {} //Useless for DynMaps + void update(T a) {} //Useless for DynMaps + };*/ + + }; +} //namespace hugo + +#endif //J_GRAPH_H diff -r 571003783202 -r 9aca797b87e8 src/work/jacint/makefile --- a/src/work/jacint/makefile Wed Feb 25 15:27:17 2004 +0000 +++ b/src/work/jacint/makefile Thu Feb 26 11:38:51 2004 +0000 @@ -3,36 +3,44 @@ CXXFLAGS = -W -Wall -ansi -pedantic LEDAROOT = /ledasrc/LEDA-4.1 -BINARIES = preflow preflow_param preflow_hl0 preflow_hl1 preflow_hl2 preflow_hl3 preflow_hl4 preflow_max_flow +BINARIES = preflow_jgraph all: $(BINARIES) makefile: .depend sinclude .depend + + +preflow_jgraph: + $(CXX3) $(CXXFLAGS) -O3 -I. -I.. -I../jacint -o preflow_jgraph preflow_jgraph.cc + +preflowalpar: + $(CXX3) $(CXXFLAGS) -O3 -I. -I.. -I../alpar -I../jacint -o preflowalpar preflowalpar.cc + preflow_max_flow: - $(CXX3) $(CXXFLAGS) -O3 -I. -I.. -I../marci -I../jacint -o preflow_max_flow preflow_max_flow.cc + $(CXX3) $(CXXFLAGS) -O3 -I. -I.. -I../jacint -o preflow_max_flow preflow_max_flow.cc preflow: - $(CXX3) $(CXXFLAGS) -O3 -I. -I.. -I../marci -I../jacint -o preflow preflow.cc + $(CXX3) $(CXXFLAGS) -O3 -I. -I.. -I../jacint -o preflow preflow.cc preflow_hl0: - $(CXX3) $(CXXFLAGS) -O3 -I. -I.. -I../marci -I../jacint -o preflow_hl0 preflow_hl0.cc + $(CXX3) $(CXXFLAGS) -O3 -I. -I.. -I../jacint -o preflow_hl0 preflow_hl0.cc preflow_hl1: - $(CXX3) $(CXXFLAGS) -O3 -I. -I.. -I../marci -I../jacint -o preflow_hl1 preflow_hl1.cc + $(CXX3) $(CXXFLAGS) -O3 -I. -I.. -I../jacint -o preflow_hl1 preflow_hl1.cc preflow_hl2: - $(CXX3) $(CXXFLAGS) -O3 -I. -I.. -I../marci -I../jacint -o preflow_hl2 preflow_hl2.cc + $(CXX3) $(CXXFLAGS) -O3 -I. -I.. -I../jacint -o preflow_hl2 preflow_hl2.cc preflow_hl3: - $(CXX3) $(CXXFLAGS) -O3 -I. -I.. -I../marci -I../jacint -o preflow_hl3 preflow_hl3.cc + $(CXX3) $(CXXFLAGS) -O3 -I. -I.. -I../jacint -o preflow_hl3 preflow_hl3.cc preflow_hl4: - $(CXX3) $(CXXFLAGS) -O3 -I. -I.. -I../marci -I../jacint -o preflow_hl4 preflow_hl4.cc + $(CXX3) $(CXXFLAGS) -O3 -I. -I.. -I../jacint -o preflow_hl4 preflow_hl4.cc preflow_param: - $(CXX3) $(CXXFLAGS) -O3 -I. -I.. -I../marci -I../jacint -o preflow_param preflow_param.cc + $(CXX3) $(CXXFLAGS) -O3 -I. -I.. -I../jacint -o preflow_param preflow_param.cc clean: $(RM) *.o $(BINARIES) .depend diff -r 571003783202 -r 9aca797b87e8 src/work/jacint/preflow_jgraph.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/work/jacint/preflow_jgraph.cc Thu Feb 26 11:38:51 2004 +0000 @@ -0,0 +1,72 @@ +#include +#include + +#include +#include +#include +#include + +using namespace hugo; + +// Use a DIMACS max flow file as stdin. +// read_dimacs_demo < dimacs_max_flow_file +int main(int, char **) { + typedef JGraph::TrivNodeIt TrivNodeIt; + typedef JGraph::EdgeIt EdgeIt; + + JGraph G; + TrivNodeIt s, t; + JGraph::EdgeMap cap(G); + readDimacsMaxFlow(std::cin, G, s, t, cap); + + std::cout << "preflow demo jacint ..." << std::endl; + + double mintime=1000000; + + for ( int i=1; i!=11; ++i ) { + double pre_time=currTime(); + preflow max_flow_test(G, s, t, cap); + double post_time=currTime(); + if ( mintime > post_time-pre_time ) mintime = post_time-pre_time; + } + + double pre_time=currTime(); + preflow max_flow_test(G, s, t, cap); + double post_time=currTime(); + + JGraph::NodeMap cut(G); + max_flow_test.minCut(cut); + int min_cut_value=0; + for(EdgeIt e=G.firstEdge(); e; G.next(e)) { + if (cut.get(G.tail(e)) && !cut.get(G.head(e))) min_cut_value+=cap.get(e); + } + + JGraph::NodeMap cut1(G); + max_flow_test.minMinCut(cut1); + int min_min_cut_value=0; + for(EdgeIt e=G.firstEdge(); e; G.next(e)) { + if (cut.get(G.tail(e)) && !cut.get(G.head(e))) + min_min_cut_value+=cap.get(e); + } + + JGraph::NodeMap cut2(G); + max_flow_test.maxMinCut(cut2); + int max_min_cut_value=0; + for(EdgeIt e=G.firstEdge(); e; G.next(e)) { + if (cut2.get(G.tail(e)) && !cut2.get(G.head(e))) + max_min_cut_value+=cap.get(e); + } + + std::cout << "min time of 10 runs: " << mintime << " sec"<< std::endl; + std::cout << "phase 0: " << max_flow_test.time-pre_time + << " sec"<< std::endl; + std::cout << "phase 1: " << post_time-max_flow_test.time + << " sec"<< std::endl; + std::cout << "flow value: "<< max_flow_test.maxFlow() << std::endl; + std::cout << "min cut value: "<< min_cut_value << std::endl; + std::cout << "min min cut value: "<< min_min_cut_value << std::endl; + std::cout << "max min cut value: "<< max_min_cut_value << + std::endl<< std::endl; + + return 0; +} diff -r 571003783202 -r 9aca797b87e8 src/work/jacint/preflow_jgraph.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/work/jacint/preflow_jgraph.h Thu Feb 26 11:38:51 2004 +0000 @@ -0,0 +1,536 @@ +// -*- C++ -*- +/* +preflow.h with 'j_graph interface' +by jacint. +Heuristics: + 2 phase + gap + list 'level_list' on the nodes on level i implemented by hand + stack 'active' on the active nodes on level i implemented by hand + runs heuristic 'highest label' for H1*n relabels + runs heuristic 'bound decrease' for H0*n relabels, starts with 'highest label' + +Parameters H0 and H1 are initialized to 20 and 10. + +The best preflow I could ever write. + +The constructor runs the algorithm. + +Members: + +T maxFlow() : returns the value of a maximum flow + +T flowOnEdge(EdgeIt e) : for a fixed maximum flow x it returns x(e) + +FlowMap Flow() : returns the fixed maximum flow x + +void minMinCut(CutMap& M) : sets M to the characteristic vector of the + minimum min cut. M should be a map of bools initialized to false. + +void maxMinCut(CutMap& M) : sets M to the characteristic vector of the + maximum min cut. M should be a map of bools initialized to false. + +void minCut(CutMap& M) : sets M to the characteristic vector of + a min cut. M should be a map of bools initialized to false. + +*/ + +#ifndef PREFLOW_H +#define PREFLOW_H + +#define H0 20 +#define H1 1 + +#include +#include + +#include + +#include + +namespace hugo { + + template , + typename CapMap=typename Graph::EdgeMap > + class preflow { + + typedef typename Graph::TrivNodeIt NodeIt; + typedef typename Graph::TrivEdgeIt EdgeIt; + typedef typename Graph::NodeIt EachNodeIt; + typedef typename Graph::OutEdgeIt OutEdgeIt; + typedef typename Graph::InEdgeIt InEdgeIt; + + Graph& G; + NodeIt s; + NodeIt t; + FlowMap flow; + CapMap& capacity; + T value; + + public: + double time; + preflow(Graph& _G, NodeIt _s, NodeIt _t, CapMap& _capacity ) : + G(_G), s(_s), t(_t), flow(_G, 0), capacity(_capacity) + { + + bool phase=0; //phase 0 is the 1st phase, phase 1 is the 2nd + int n=G.numNodes(); + int heur0=(int)(H0*n); //time while running 'bound decrease' + int heur1=(int)(H1*n); //time while running 'highest label' + int heur=heur1; //starting time interval (#of relabels) + bool what_heur=1; + /* + what_heur is 0 in case 'bound decrease' + and 1 in case 'highest label' + */ + bool end=false; + /* + Needed for 'bound decrease', 'true' + means no active nodes are above bound b. + */ + int relabel=0; + int k=n-2; //bound on the highest level under n containing a node + int b=k; //bound on the highest level under n of an active node + + typename Graph::NodeMap level(G,n); + typename Graph::NodeMap excess(G); + + std::vector active(n); + typename Graph::NodeMap next(G); + //Stack of the active nodes in level i < n. + //We use it in both phases. + + typename Graph::NodeMap left(G); + typename Graph::NodeMap right(G); + std::vector level_list(n); + /* + List of the nodes in level i bfs_queue; + bfs_queue.push(t); + + while (!bfs_queue.empty()) { + + NodeIt v=bfs_queue.front(); + bfs_queue.pop(); + int l=level.get(v)+1; + + for(InEdgeIt e=G.firstIn(v); e; G.next(e)) { + NodeIt w=G.tail(e); + if ( level.get(w) == n && w != s ) { + bfs_queue.push(w); + NodeIt first=level_list[l]; + if ( first ) left.set(first,w); + right.set(w,first); + level_list[l]=w; + level.set(w, l); + } + } + } + + level.set(s,n); + + + /* Starting flow. It is everywhere 0 at the moment. */ + for(OutEdgeIt e=G.firstOut(s); e; G.next(e)) + { + T c=capacity.get(e); + if ( c == 0 ) continue; + NodeIt w=G.head(e); + if ( level.get(w) < n ) { + if ( excess.get(w) == 0 && w!=t ) { + next.set(w,active[level.get(w)]); + active[level.get(w)]=w; + } + flow.set(e, c); + excess.set(w, excess.get(w)+c); + } + } + + /* + End of preprocessing + */ + + + + /* + Push/relabel on the highest level active nodes. + */ + while ( true ) { + + if ( b == 0 ) { + if ( phase ) break; + + if ( !what_heur && !end && k > 0 ) { + b=k; + end=true; + } else { + phase=1; + time=currTime(); + level.set(s,0); + std::queue bfs_queue; + bfs_queue.push(s); + + while (!bfs_queue.empty()) { + + NodeIt v=bfs_queue.front(); + bfs_queue.pop(); + int l=level.get(v)+1; + + for(InEdgeIt e=G.firstIn(v); e; G.next(e)) { + if ( capacity.get(e) == flow.get(e) ) continue; + NodeIt u=G.tail(e); + if ( level.get(u) >= n ) { + bfs_queue.push(u); + level.set(u, l); + if ( excess.get(u) > 0 ) { + next.set(u,active[l]); + active[l]=u; + } + } + } + + for(OutEdgeIt e=G.firstOut(v); e; G.next(e)) { + if ( 0 == flow.get(e) ) continue; + NodeIt u=G.head(e); + if ( level.get(u) >= n ) { + bfs_queue.push(u); + level.set(u, l); + if ( excess.get(u) > 0 ) { + next.set(u,active[l]); + active[l]=u; + } + } + } + } + b=n-2; + } + + } + + + if ( !active[b] ) --b; + else { + end=false; + + NodeIt w=active[b]; + active[b]=next.get(w); + int lev=level.get(w); + T exc=excess.get(w); + int newlevel=n; //bound on the next level of w + + for(OutEdgeIt e=G.firstOut(w); e; G.next(e)) { + + if ( flow.get(e) == capacity.get(e) ) continue; + NodeIt v=G.head(e); + //e=wv + + if( lev > level.get(v) ) { + /*Push is allowed now*/ + + if ( excess.get(v)==0 && v!=t && v!=s ) { + int lev_v=level.get(v); + next.set(v,active[lev_v]); + active[lev_v]=v; + } + + T cap=capacity.get(e); + T flo=flow.get(e); + T remcap=cap-flo; + + if ( remcap >= exc ) { + /*A nonsaturating push.*/ + + flow.set(e, flo+exc); + excess.set(v, excess.get(v)+exc); + exc=0; + break; + + } else { + /*A saturating push.*/ + + flow.set(e, cap); + excess.set(v, excess.get(v)+remcap); + exc-=remcap; + } + } else if ( newlevel > level.get(v) ){ + newlevel = level.get(v); + } + + } //for out edges wv + + + if ( exc > 0 ) { + for( InEdgeIt e=G.firstIn(w); e; G.next(e)) { + + if( flow.get(e) == 0 ) continue; + NodeIt v=G.tail(e); + //e=vw + + if( lev > level.get(v) ) { + /*Push is allowed now*/ + + if ( excess.get(v)==0 && v!=t && v!=s ) { + int lev_v=level.get(v); + next.set(v,active[lev_v]); + active[lev_v]=v; + } + + T flo=flow.get(e); + + if ( flo >= exc ) { + /*A nonsaturating push.*/ + + flow.set(e, flo-exc); + excess.set(v, excess.get(v)+exc); + exc=0; + break; + } else { +/*A saturating push.*/ + + excess.set(v, excess.get(v)+flo); + exc-=flo; + flow.set(e,0); + } + } else if ( newlevel > level.get(v) ) { + newlevel = level.get(v); + } + } //for in edges vw + + } // if w still has excess after the out edge for cycle + + excess.set(w, exc); + + /* + Relabel + */ + + + if ( exc > 0 ) { + //now 'lev' is the old level of w + + if ( phase ) { + level.set(w,++newlevel); + next.set(w,active[newlevel]); + active[newlevel]=w; + b=newlevel; + } else { + //unlacing starts + NodeIt right_n=right.get(w); + NodeIt left_n=left.get(w); + + if ( right_n ) { + if ( left_n ) { + right.set(left_n, right_n); + left.set(right_n, left_n); + } else { + level_list[lev]=right_n; + left.set(right_n, NodeIt()); + } + } else { + if ( left_n ) { + right.set(left_n, NodeIt()); + } else { + level_list[lev]=NodeIt(); + + } + } + //unlacing ends + + //gapping starts + if ( !level_list[lev] ) { + + for (int i=lev; i!=k ; ) { + NodeIt v=level_list[++i]; + while ( v ) { + level.set(v,n); + v=right.get(v); + } + level_list[i]=NodeIt(); + if ( !what_heur ) active[i]=NodeIt(); + } + + level.set(w,n); + b=lev-1; + k=b; + //gapping ends + } else { + + if ( newlevel == n ) level.set(w,n); + else { + level.set(w,++newlevel); + next.set(w,active[newlevel]); + active[newlevel]=w; + if ( what_heur ) b=newlevel; + if ( k < newlevel ) ++k; + NodeIt first=level_list[newlevel]; + if ( first ) left.set(first,w); + right.set(w,first); + left.set(w,NodeIt()); + level_list[newlevel]=w; + } + } + + + ++relabel; + if ( relabel >= heur ) { + relabel=0; + if ( what_heur ) { + what_heur=0; + heur=heur0; + end=false; + } else { + what_heur=1; + heur=heur1; + b=k; + } + } + } //phase 0 + + + } // if ( exc > 0 ) + + + } // if stack[b] is nonempty + + } // while(true) + + + value = excess.get(t); + /*Max flow value.*/ + + } //void run() + + + + + + /* + Returns the maximum value of a flow. + */ + + T maxFlow() { + return value; + } + + + + /* + For the maximum flow x found by the algorithm, + it returns the flow value on edge e, i.e. x(e). + */ + + T flowOnEdge(EdgeIt e) { + return flow.get(e); + } + + + + FlowMap Flow() { + return flow; + } + + + + void Flow(FlowMap& _flow ) { + for(EachNodeIt v=G.firstNode() ; v; G.next(v)) + _flow.set(v,flow.get(v)); + } + + + + /* + Returns the minimum min cut, by a bfs from s in the residual graph. + */ + + template + void minMinCut(_CutMap& M) { + + std::queue queue; + + M.set(s,true); + queue.push(s); + + while (!queue.empty()) { + NodeIt w=queue.front(); + queue.pop(); + + for(OutEdgeIt e=G.firstOut(w) ; e; G.next(e)) { + NodeIt v=G.head(e); + if (!M.get(v) && flow.get(e) < capacity.get(e) ) { + queue.push(v); + M.set(v, true); + } + } + + for(InEdgeIt e=G.firstIn(w) ; e; G.next(e)) { + NodeIt v=G.tail(e); + if (!M.get(v) && flow.get(e) > 0 ) { + queue.push(v); + M.set(v, true); + } + } + } + } + + + + /* + Returns the maximum min cut, by a reverse bfs + from t in the residual graph. + */ + + template + void maxMinCut(_CutMap& M) { + + std::queue queue; + + M.set(t,true); + queue.push(t); + + while (!queue.empty()) { + NodeIt w=queue.front(); + queue.pop(); + + for(InEdgeIt e=G.firstIn(w) ; e; G.next(e)) { + NodeIt v=G.tail(e); + if (!M.get(v) && flow.get(e) < capacity.get(e) ) { + queue.push(v); + M.set(v, true); + } + } + + for(OutEdgeIt e=G.firstOut(w) ; e; G.next(e)) { + NodeIt v=G.head(e); + if (!M.get(v) && flow.get(e) > 0 ) { + queue.push(v); + M.set(v, true); + } + } + } + + for(EachNodeIt v=G.firstNode() ; v; G.next(v)) { + M.set(v, !M.get(v)); + } + + } + + + + template + void minCut(CutMap& M) { + minMinCut(M); + } + + + }; +}//namespace marci +#endif + + + +