diff -r f1de2ab64e1c -r d2ac583ed195 src/work/jacint/preflow_hl3.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/work/jacint/preflow_hl3.h Wed Feb 18 21:50:45 2004 +0000 @@ -0,0 +1,472 @@ +// -*- C++ -*- +/* +preflow_hl3.h +by jacint. +Runs the highest label variant of the preflow push algorithm with +running time O(n^2\sqrt(m)), with the felszippantos 'empty level' +and with the two-phase heuristic: if there is no active node of +level at most n, then we go into phase 1, do a bfs +from s, and flow the excess back to s. + +In phase 1 we shift everything downwards by n. + +'A' is a parameter for the empty_level heuristic + +Member functions: + +void run() : runs the algorithm + + The following functions should be used after run() was already run. + +T maxflow() : returns the value of a maximum flow + +T flowonedge(EdgeIt e) : for a fixed maximum flow x it returns x(e) + +FlowMap allflow() : returns the fixed maximum flow x + +void mincut(CutMap& M) : sets M to the characteristic vector of a + minimum cut. M should be a map of bools initialized to false. + +void min_mincut(CutMap& M) : sets M to the characteristic vector of the + minimum min cut. M should be a map of bools initialized to false. + +void max_mincut(CutMap& M) : sets M to the characteristic vector of the + maximum min cut. M should be a map of bools initialized to false. + +*/ + +#ifndef PREFLOW_HL3_H +#define PREFLOW_HL3_H + +#define A 1 + +#include +#include +#include + +namespace marci { + + template , typename CapMap=typename Graph::EdgeMap, + typename IntMap=typename Graph::NodeMap, typename TMap=typename Graph::NodeMap > + class preflow_hl3 { + + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::EdgeIt EdgeIt; + typedef typename Graph::EachNodeIt EachNodeIt; + typedef typename Graph::OutEdgeIt OutEdgeIt; + typedef typename Graph::InEdgeIt InEdgeIt; + + Graph& G; + NodeIt s; + NodeIt t; + FlowMap flow; + CapMap& capacity; + T value; + + public: + + preflow_hl3(Graph& _G, NodeIt _s, NodeIt _t, CapMap& _capacity) : + G(_G), s(_s), t(_t), flow(_G, 0), capacity(_capacity) { } + + + void run() { + + bool phase=0; + int n=G.nodeNum(); + int b=n-2; + /* + b is a bound on the highest level of the stack. + In the beginning it is at most n-2. + */ + + IntMap level(G,n); + TMap excess(G); + + std::vector numb(n); + /* + The number of nodes on level i < n. It is + initialized to n+1, because of the reverse_bfs-part. + Needed only in phase 0. + */ + + std::vector > stack(n); + //Stack of the active nodes in level i < n. + //We use it in both phases. + + + /*Reverse_bfs from t, to find the starting level.*/ + level.set(t,0); + std::queue 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.template first(v); e.valid(); ++e) { + NodeIt w=G.tail(e); + if ( level.get(w) == n ) { + bfs_queue.push(w); + ++numb[l]; + level.set(w, l); + } + } + } + + level.set(s,n); + + + + /* Starting flow. It is everywhere 0 at the moment. */ + for(OutEdgeIt e=G.template first(s); e.valid(); ++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 ) stack[level.get(w)].push(w); + flow.set(e, c); + excess.set(w, excess.get(w)+c); + } + } + + /* + End of preprocessing + */ + + + + /* + Push/relabel on the highest level active nodes. + */ + /*While there exists an active node.*/ + while ( true ) { + + if ( b == 0 ) { + if ( phase ) break; + phase=1; + + 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.template first(v); e.valid(); ++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 ) stack[l].push(u); + } + } + + for(OutEdgeIt e=G.template first(v); e.valid(); ++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 ) stack[l].push(u); + } + } + } + + b=n-2; + } + + if ( stack[b].empty() ) --b; + else { + + NodeIt w=stack[b].top(); //w is a highest label active node. + stack[b].pop(); + int lev=level.get(w); + int exc=excess.get(w); + int newlevel=n; //In newlevel we bound the next level of w. + + for(OutEdgeIt e=G.template first(w); e.valid(); ++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 ) + stack[level.get(v)].push(v); + /*v becomes active.*/ + + int cap=capacity.get(e); + int flo=flow.get(e); + int 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.template first(w); e.valid(); ++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 ) + stack[level.get(v)].push(v); + /*v becomes active.*/ + + int 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); + stack[newlevel].push(w); + b=newlevel; + } else { + + if ( newlevel >= n-2 || --numb[lev] == 0 ) { + + level.set(w,n); + + if ( newlevel < n ) { + + std::queue bfs_queue; + bfs_queue.push(w); + + while (!bfs_queue.empty()) { + + NodeIt v=bfs_queue.front(); + bfs_queue.pop(); + + for(OutEdgeIt e=G.template first(v); e.valid(); ++e) { + if ( capacity.get(e) == flow.get(e) ) continue; + NodeIt u=G.head(e); + if ( level.get(u) < n ) { + bfs_queue.push(u); + --numb[level.get(u)]; + level.set(u, n); + } + } + + for(InEdgeIt e=G.template first(v); e.valid(); ++e) { + if ( 0 == flow.get(e) ) continue; + NodeIt u=G.tail(e); + if ( level.get(u) < n ) { + bfs_queue.push(u); + --numb[level.get(u)]; + level.set(u, n); + } + } + } + } + b=n-1; + + } else { + level.set(w,++newlevel); + stack[newlevel].push(w); + ++numb[newlevel]; + b=newlevel; + } + } + } + + + + } // 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); + } + + + + /* + Returns the maximum flow x found by the algorithm. + */ + + FlowMap allflow() { + return flow; + } + + + + + /* + Returns the minimum min cut, by a bfs from s in the residual graph. + */ + + template + void mincut(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.template first(w) ; e.valid(); ++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.template first(w) ; e.valid(); ++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 max_mincut(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.template first(w) ; e.valid(); ++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.template first(w) ; e.valid(); ++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.template first() ; v.valid(); ++v) { + M.set(v, !M.get(v)); + } + + } + + + + template + void min_mincut(CutMap& M) { + mincut(M); + } + + + + }; +}//namespace marci +#endif + + + +