diff -r e2e18eb0fd10 -r a5127ecb2914 src/work/jacint/preflow_push_max_flow.h --- a/src/work/jacint/preflow_push_max_flow.h Wed Feb 18 13:06:41 2004 +0000 +++ b/src/work/jacint/preflow_push_max_flow.h Wed Feb 18 14:42:38 2004 +0000 @@ -1,3 +1,4 @@ +// -*- C++ -*- /* preflow_push_max_flow_h by jacint. @@ -15,13 +16,16 @@ T maxflow() : returns the value of a maximum flow -NodeMap mincut(): returns a - characteristic vector of a minimum cut. +void mincut(CutMap& M) : sets M to the characteristic vector of a + minimum cut. M should be a map of bools initialized to false. + */ #ifndef PREFLOW_PUSH_MAX_FLOW_H #define PREFLOW_PUSH_MAX_FLOW_H +#define A 1 + #include #include #include @@ -31,7 +35,9 @@ namespace marci { - template + template , typename CapMap=typename Graph::EdgeMap, + typename IntMap=typename Graph::NodeMap, typename TMap=typename Graph::NodeMap > class preflow_push_max_flow { typedef typename Graph::NodeIt NodeIt; @@ -42,17 +48,15 @@ Graph& G; NodeIt s; NodeIt t; - typename Graph::EdgeMap& capacity; - T value; - typename Graph::NodeMap mincutvector; - - - + IntMap level; + CapMap& capacity; + int empty_level; //an empty level in the end of run() + T value; + public: - - preflow_push_max_flow ( Graph& _G, NodeIt _s, NodeIt _t, - typename Graph::EdgeMap& _capacity) : - G(_G), s(_s), t(_t), capacity(_capacity), mincutvector(_G, false) { } + + preflow_push_max_flow(Graph& _G, NodeIt _s, NodeIt _t, CapMap& _capacity) : + G(_G), s(_s), t(_t), level(_G), capacity(_capacity) { } /* @@ -62,223 +66,200 @@ */ void run() { - typename Graph::EdgeMap flow(G, 0); - typename Graph::NodeMap level(G); - typename Graph::NodeMap excess(G); - - int n=G.nodeNum(); + int n=G.nodeNum(); int b=n-2; /* - b is a bound on the highest level of an active Node. - In the beginning it is at most n-2. + b is a bound on the highest level of an active node. */ - - std::vector numb(n); //The number of Nodes on level i < n. - std::vector > stack(2*n-1); - //Stack of the active Nodes in level i. + + IntMap level(G,n); + TMap excess(G); + FlowMap flow(G,0); + + std::vector numb(n); + /* + The number of nodes on level i < n. It is + initialized to n+1, because of the reverse_bfs-part. + */ + + std::vector > stack(n); + //Stack of the active nodes in level i. + /*Reverse_bfs from t, to find the starting level.*/ - reverse_bfs bfs(G, t); - bfs.run(); - for(EachNodeIt v=G.template first(); v.valid(); ++v) - { - int dist=bfs.dist(v); - level.set(v, dist); - ++numb[dist]; + 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. */ + + + /* Starting flow. It is everywhere 0 at the moment. */ for(OutEdgeIt e=G.template first(s); e.valid(); ++e) { - if ( capacity.get(e) > 0 ) { - NodeIt w=G.head(e); + if ( capacity.get(e) == 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, capacity.get(e)); - stack[level.get(w)].push(w); excess.set(w, excess.get(w)+capacity.get(e)); } } - + /* End of preprocessing */ + /* + Push/relabel on the highest level active nodes. + */ + /*While there exists an active node.*/ + while (b) { + if ( stack[b].empty() ) { + --b; + continue; + } + + 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=2*n-2; //In newlevel we bound the next level of w. + + // if ( level.get(w) < n ) { //Nem tudom ez mukodik-e + 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 != s && v !=t ) + 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 != s && v !=t) + 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 + level.set(w,++newlevel); + --numb[lev]; + + if ( !numb[lev] && lev < A*n ) { //If the level of w gets empty. + + for (EachNodeIt v=G.template first(); v.valid() ; ++v) { + if (level.get(v) > lev ) level.set(v,n); + } + for (int i=lev+1 ; i!=n ; ++i) numb[i]=0; + if ( newlevel < n ) newlevel=n; + } else if ( newlevel < n ) { + ++numb[newlevel]; + stack[newlevel].push(w); + b=newlevel; + } + } - /* - Push/relabel on the highest level active Nodes. - */ - - /*While there exists an active Node.*/ - while (b) { - /*We decrease the bound if there is no active node of level b.*/ - if (stack[b].empty()) { - --b; - } else { - NodeIt w=stack[b].top(); //w is the highest label active Node. - stack[b].pop(); //We delete w from the stack. - - int newlevel=2*n-2; //In newlevel we maintain the next level of w. - - for(OutEdgeIt e=G.template first(w); e.valid(); ++e) { - NodeIt v=G.head(e); - /*e is the Edge wv.*/ - - if (flow.get(e) excess.get(w)) { - /*A nonsaturating push.*/ - - if (excess.get(v)==0 && v != s) stack[level.get(v)].push(v); - /*v becomes active.*/ - - flow.set(e, flow.get(e)+excess.get(w)); - excess.set(v, excess.get(v)+excess.get(w)); - excess.set(w,0); - //std::cout << w << " " << v <<" elore elen nonsat pump " << std::endl; - break; - } else { - /*A saturating push.*/ - - if (excess.get(v)==0 && v != s) stack[level.get(v)].push(v); - /*v becomes active.*/ - - excess.set(v, excess.get(v)+capacity.get(e)-flow.get(e)); - excess.set(w, excess.get(w)-capacity.get(e)+flow.get(e)); - flow.set(e, capacity.get(e)); - //std::cout << w <<" " << v <<" elore elen sat pump " << std::endl; - if (excess.get(w)==0) break; - /*If w is not active any more, then we go on to the next Node.*/ - - } // if (capacity.get(e)-flow.get(e) > excess.get(w)) - } // if (level.get(w)==level.get(v)+1) - - else {newlevel = newlevel < level.get(v) ? newlevel : level.get(v);} - - } //if (flow.get(e)(w); e.valid(); ++e) { - NodeIt v=G.tail(e); - /*e is the Edge vw.*/ - - if (excess.get(w)==0) break; - /*It may happen, that w became inactive in the first 'for' cycle.*/ - - if(flow.get(e)>0) { - /*e is an Edge of the residual graph */ - - if(level.get(w)==level.get(v)+1) { - /*Push is allowed now*/ - - if (flow.get(e) > excess.get(w)) { - /*A nonsaturating push.*/ - - if (excess.get(v)==0 && v != s) stack[level.get(v)].push(v); - /*v becomes active.*/ - - flow.set(e, flow.get(e)-excess.get(w)); - excess.set(v, excess.get(v)+excess.get(w)); - excess.set(w,0); - //std::cout << v << " " << w << " vissza elen nonsat pump " << std::endl; - break; - } else { - /*A saturating push.*/ - - if (excess.get(v)==0 && v != s) stack[level.get(v)].push(v); - /*v becomes active.*/ - - flow.set(e,0); - excess.set(v, excess.get(v)+flow.get(e)); - excess.set(w, excess.get(w)-flow.get(e)); - //std::cout << v <<" " << w << " vissza elen sat pump " << std::endl; - if (excess.get(w)==0) { break;} - } //if (flow.get(e) > excess.get(v)) - } //if(level.get(w)==level.get(v)+1) - - else {newlevel = newlevel < level.get(v) ? newlevel : level.get(v);} - //std::cout << "Leveldecrease of Node " << w << " to " << newlevel << std::endl; - - } //if (flow.get(e)>0) - - } //for in-Edge - - - - - /* - Relabel - */ - if (excess.get(w)>0) { - /*Now newlevel <= n*/ - - int l=level.get(w); //l is the old level of w. - --numb[l]; - - if (newlevel == n) { - level.set(w,n); - - } else { - - if (numb[l]) { - /*If the level of w remains nonempty.*/ - - level.set(w,++newlevel); - ++numb[newlevel]; - stack[newlevel].push(w); - b=newlevel; - } else { - /*If the level of w gets empty.*/ - - for (EachNodeIt v=G.template first(); v.valid() ; ++v) { - if (level.get(v) >= l ) { - level.set(v,n); - } - } - - for (int i=l+1 ; i!=n ; ++i) numb[i]=0; - } //if (numb[l]) - - } // if (newlevel = n) - - } // if (excess.get(w)>0) - - - } //else - } //while(b) value=excess.get(t); /*Max flow value.*/ - - /* - We find an empty level, e. The Nodes above this level give - a minimum cut. + /* + We count empty_level. The nodes above this level is a mincut. */ - - int e=1; - - while(e) { - if(numb[e]) ++e; + while(true) { + if(numb[empty_level]) ++empty_level; else break; } - for (EachNodeIt v=G.template first(); v.valid(); ++v) { - if (level.get(v) > e) mincutvector.set(v, true); - } - } // void run() @@ -295,12 +276,15 @@ /* Returns a minimum cut. - */ - - typename Graph::NodeMap mincut() { - return mincutvector; + */ + template + void mincut(CutMap& M) { + + for (EachNodeIt v=G.template first(); v.valid(); ++v) { + if ( level.get(v) > empty_level ) M.set(v, true); + } } - + }; }//namespace marci