// -*- C++ -*- /* preflow_param.h by jacint. For testing the parameters H0, H1 of preflow.h 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) : fast function, sets M to the characteristic vector of a minimum cut. Different member from the other preflow_hl-s (here we have a member 'NodeMap cut'). CutMap minCut() : fast function, giving the characteristic vector of a minimum cut. */ #ifndef PREFLOW_PARAM_H #define PREFLOW_PARAM_H #include #include #include //for test namespace hugo { template , typename CapMap=typename Graph::EdgeMap > class preflow_param { 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; int H0; int H1; public: double time; preflow_param(Graph& _G, NodeIt _s, NodeIt _t, CapMap& _capacity, int _H0, int _H1) : G(_G), s(_s), t(_t), flow(_G, 0), capacity(_capacity), H0(_H0), H1(_H1) { bool phase=0; //phase 0 is the 1st phase, phase 1 is the 2nd int n=G.nodeNum(); 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; //for the 0 case /* Needed for 'bound decrease', 'true' means no active nodes are above bound b. */ int relabel=0; int k=n-2; int b=k; /* b is a bound on the highest level of the stack. k is a bound on the highest nonempty level i < n. */ 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); /* Needed for the list of the nodes in level i. */ /*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 && w != s ) { bfs_queue.push(w); NodeIt first=level_list[l]; if ( first != 0 ) 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.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 ) { 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 { time=currTime(); 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 ) { next.set(u,active[l]); active[l]=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 ) { next.set(u,active[l]); active[l]=u; } } } } b=n-2; } } if ( active[b] == 0 ) --b; else { end=false; //needed only for phase 0, case hl2 NodeIt w=active[b]; //w is a highest label active node. active[b]=next.get(w); int lev=level.get(w); T 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 ) { int lev_v=level.get(v); next.set(v,active[lev_v]); active[lev_v]=v; } /*v becomes active.*/ 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.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 ) { int lev_v=level.get(v); next.set(v,active[lev_v]); active[lev_v]=v; /*v becomes active.*/ } 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 NodeIt right_n=right.get(w); NodeIt left_n=left.get(w); if ( right_n != 0 ) { if ( left_n != 0 ) { right.set(left_n, right_n); left.set(right_n, left_n); } else { level_list[lev]=right_n; left.set(right_n, 0); } } else { if ( left_n != 0 ) { right.set(left_n, 0); } else { level_list[lev]=0; } } if ( level_list[lev]==0 ) { for (int i=lev; i!=k ; ) { NodeIt v=level_list[++i]; while ( v != 0 ) { level.set(v,n); v=right.get(v); } level_list[i]=0; if ( !what_heur ) active[i]=0; } level.set(w,n); b=lev-1; k=b; } 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 != 0 ) left.set(first,w); right.set(w,first); left.set(w,0); 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.template first() ; v.valid(); ++v) _flow.set(v,flow.get(v)); } /* 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 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.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 minMinCut(CutMap& M) { minCut(M); } }; }//namespace #endif