jacint@97: // -*- C++ -*- jacint@78: /* jacint@78: preflow_push_max_flow_h jacint@78: by jacint. jacint@78: Runs a preflow push algorithm with the modification, jacint@83: that we do not push on nodes with level at least n. jacint@83: Moreover, if a level gets empty, we set all nodes above that jacint@78: level to level n. Hence, in the end, we arrive at a maximum preflow jacint@78: with value of a max flow value. An empty level gives a minimum cut. jacint@78: jacint@78: Member functions: jacint@78: jacint@78: void run() : runs the algorithm jacint@78: jacint@78: The following functions should be used after run() was already run. jacint@78: jacint@78: T maxflow() : returns the value of a maximum flow jacint@78: jacint@97: void mincut(CutMap& M) : sets M to the characteristic vector of a jacint@97: minimum cut. M should be a map of bools initialized to false. jacint@97: jacint@78: */ jacint@78: jacint@78: #ifndef PREFLOW_PUSH_MAX_FLOW_H jacint@78: #define PREFLOW_PUSH_MAX_FLOW_H jacint@78: jacint@97: #define A 1 jacint@97: jacint@78: #include jacint@78: #include jacint@78: #include jacint@78: jacint@78: #include jacint@78: jacint@78: alpar@105: namespace hugo { jacint@78: jacint@97: template , typename CapMap=typename Graph::EdgeMap, jacint@97: typename IntMap=typename Graph::NodeMap, typename TMap=typename Graph::NodeMap > jacint@78: class preflow_push_max_flow { jacint@78: jacint@78: typedef typename Graph::NodeIt NodeIt; jacint@78: typedef typename Graph::EachNodeIt EachNodeIt; jacint@78: typedef typename Graph::OutEdgeIt OutEdgeIt; jacint@78: typedef typename Graph::InEdgeIt InEdgeIt; jacint@78: jacint@78: Graph& G; jacint@78: NodeIt s; jacint@78: NodeIt t; jacint@97: IntMap level; jacint@97: CapMap& capacity; jacint@97: int empty_level; //an empty level in the end of run() jacint@97: T value; jacint@97: jacint@78: public: jacint@97: jacint@97: preflow_push_max_flow(Graph& _G, NodeIt _s, NodeIt _t, CapMap& _capacity) : jacint@97: G(_G), s(_s), t(_t), level(_G), capacity(_capacity) { } jacint@78: jacint@78: jacint@78: /* jacint@83: The run() function runs a modified version of the jacint@83: highest label preflow-push, which only jacint@78: finds a maximum preflow, hence giving the value of a maximum flow. jacint@78: */ jacint@78: void run() { jacint@78: jacint@97: int n=G.nodeNum(); jacint@78: int b=n-2; jacint@83: /* jacint@97: b is a bound on the highest level of an active node. jacint@83: */ jacint@97: jacint@97: IntMap level(G,n); jacint@97: TMap excess(G); jacint@97: FlowMap flow(G,0); jacint@97: jacint@97: std::vector numb(n); jacint@97: /* jacint@97: The number of nodes on level i < n. It is jacint@97: initialized to n+1, because of the reverse_bfs-part. jacint@97: */ jacint@97: jacint@97: std::vector > stack(n); jacint@97: //Stack of the active nodes in level i. jacint@97: jacint@78: jacint@78: /*Reverse_bfs from t, to find the starting level.*/ jacint@97: level.set(t,0); jacint@97: std::queue bfs_queue; jacint@97: bfs_queue.push(t); jacint@97: jacint@97: while (!bfs_queue.empty()) { jacint@97: jacint@97: NodeIt v=bfs_queue.front(); jacint@97: bfs_queue.pop(); jacint@97: int l=level.get(v)+1; jacint@97: jacint@97: for(InEdgeIt e=G.template first(v); e.valid(); ++e) { jacint@97: NodeIt w=G.tail(e); jacint@97: if ( level.get(w) == n ) { jacint@97: bfs_queue.push(w); jacint@97: ++numb[l]; jacint@97: level.set(w, l); jacint@97: } jacint@78: } jacint@97: } jacint@97: jacint@78: level.set(s,n); jacint@78: jacint@97: jacint@97: jacint@97: /* Starting flow. It is everywhere 0 at the moment. */ jacint@83: for(OutEdgeIt e=G.template first(s); e.valid(); ++e) jacint@78: { jacint@97: if ( capacity.get(e) == 0 ) continue; jacint@97: NodeIt w=G.head(e); jacint@97: if ( level.get(w) < n ) { jacint@97: if ( excess.get(w) == 0 && w!=t ) stack[level.get(w)].push(w); jacint@83: flow.set(e, capacity.get(e)); jacint@83: excess.set(w, excess.get(w)+capacity.get(e)); jacint@83: } jacint@78: } jacint@97: jacint@78: /* jacint@78: End of preprocessing jacint@78: */ jacint@78: jacint@78: jacint@97: /* jacint@97: Push/relabel on the highest level active nodes. jacint@97: */ jacint@97: /*While there exists an active node.*/ jacint@97: while (b) { jacint@97: if ( stack[b].empty() ) { jacint@97: --b; jacint@97: continue; jacint@97: } jacint@97: jacint@97: NodeIt w=stack[b].top(); //w is a highest label active node. jacint@97: stack[b].pop(); jacint@97: int lev=level.get(w); jacint@97: int exc=excess.get(w); jacint@97: int newlevel=2*n-2; //In newlevel we bound the next level of w. jacint@97: jacint@97: // if ( level.get(w) < n ) { //Nem tudom ez mukodik-e jacint@97: for(OutEdgeIt e=G.template first(w); e.valid(); ++e) { jacint@97: jacint@97: if ( flow.get(e) == capacity.get(e) ) continue; jacint@97: NodeIt v=G.head(e); jacint@97: //e=wv jacint@97: jacint@97: if( lev > level.get(v) ) { jacint@97: /*Push is allowed now*/ jacint@97: jacint@97: if ( excess.get(v)==0 && v != s && v !=t ) jacint@97: stack[level.get(v)].push(v); jacint@97: /*v becomes active.*/ jacint@97: jacint@97: int cap=capacity.get(e); jacint@97: int flo=flow.get(e); jacint@97: int remcap=cap-flo; jacint@97: jacint@97: if ( remcap >= exc ) { jacint@97: /*A nonsaturating push.*/ jacint@97: jacint@97: flow.set(e, flo+exc); jacint@97: excess.set(v, excess.get(v)+exc); jacint@97: exc=0; jacint@97: break; jacint@97: jacint@97: } else { jacint@97: /*A saturating push.*/ jacint@97: jacint@97: flow.set(e, cap ); jacint@97: excess.set(v, excess.get(v)+remcap); jacint@97: exc-=remcap; jacint@97: } jacint@97: } else if ( newlevel > level.get(v) ) newlevel = level.get(v); jacint@97: jacint@97: } //for out edges wv jacint@97: jacint@97: jacint@97: if ( exc > 0 ) { jacint@97: for( InEdgeIt e=G.template first(w); e.valid(); ++e) { jacint@97: jacint@97: if( flow.get(e) == 0 ) continue; jacint@97: NodeIt v=G.tail(e); jacint@97: //e=vw jacint@97: jacint@97: if( lev > level.get(v) ) { jacint@97: /*Push is allowed now*/ jacint@97: jacint@97: if ( excess.get(v)==0 && v != s && v !=t) jacint@97: stack[level.get(v)].push(v); jacint@97: /*v becomes active.*/ jacint@97: jacint@97: int flo=flow.get(e); jacint@97: jacint@97: if ( flo >= exc ) { jacint@97: /*A nonsaturating push.*/ jacint@97: jacint@97: flow.set(e, flo-exc); jacint@97: excess.set(v, excess.get(v)+exc); jacint@97: exc=0; jacint@97: break; jacint@97: } else { jacint@97: /*A saturating push.*/ jacint@97: jacint@97: excess.set(v, excess.get(v)+flo); jacint@97: exc-=flo; jacint@97: flow.set(e,0); jacint@97: } jacint@97: } else if ( newlevel > level.get(v) ) newlevel = level.get(v); jacint@97: jacint@97: } //for in edges vw jacint@97: jacint@97: } // if w still has excess after the out edge for cycle jacint@97: jacint@97: excess.set(w, exc); jacint@97: jacint@97: jacint@97: /* jacint@97: Relabel jacint@97: */ jacint@97: jacint@97: if ( exc > 0 ) { jacint@97: //now 'lev' is the old level of w jacint@97: level.set(w,++newlevel); jacint@97: --numb[lev]; jacint@97: jacint@97: if ( !numb[lev] && lev < A*n ) { //If the level of w gets empty. jacint@97: jacint@97: for (EachNodeIt v=G.template first(); v.valid() ; ++v) { jacint@97: if (level.get(v) > lev ) level.set(v,n); jacint@97: } jacint@97: for (int i=lev+1 ; i!=n ; ++i) numb[i]=0; jacint@97: if ( newlevel < n ) newlevel=n; jacint@97: } else if ( newlevel < n ) { jacint@97: ++numb[newlevel]; jacint@97: stack[newlevel].push(w); jacint@97: b=newlevel; jacint@97: } jacint@97: } jacint@78: jacint@78: jacint@78: jacint@78: } //while(b) jacint@78: jacint@78: value=excess.get(t); jacint@78: /*Max flow value.*/ jacint@78: jacint@78: jacint@97: /* jacint@97: We count empty_level. The nodes above this level is a mincut. jacint@78: */ jacint@97: while(true) { jacint@97: if(numb[empty_level]) ++empty_level; jacint@78: else break; jacint@78: } jacint@78: jacint@78: } // void run() jacint@78: jacint@78: jacint@78: jacint@78: /* jacint@78: Returns the maximum value of a flow. jacint@78: */ jacint@78: jacint@78: T maxflow() { jacint@78: return value; jacint@78: } jacint@78: jacint@78: jacint@78: jacint@78: /* jacint@78: Returns a minimum cut. jacint@97: */ jacint@97: template jacint@97: void mincut(CutMap& M) { jacint@97: jacint@97: for (EachNodeIt v=G.template first(); v.valid(); ++v) { jacint@97: if ( level.get(v) > empty_level ) M.set(v, true); jacint@97: } jacint@78: } jacint@97: jacint@78: jacint@78: }; alpar@105: }//namespace hugo jacint@78: #endif jacint@78: jacint@78: jacint@78: jacint@78: jacint@78: