// -*- C++ -*- /* preflow_max_flow.h by jacint. Runs the first phase of preflow.h The constructor runs the algorithm. Members: T maxFlow() : returns the value of a maximum flow CutMap minCut() : returns the characteristic vector of a min cut. */ #ifndef PREFLOW_MAX_FLOW_H #define PREFLOW_MAX_FLOW_H #define H0 20 #define H1 1 #include #include namespace hugo { template , typename CapMap=typename Graph::EdgeMap, typename CutMap=typename Graph::NodeMap > class preflow_max_flow { 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; CutMap cut; T value; public: preflow_max_flow(Graph& _G, NodeIt _s, NodeIt _t, CapMap& _capacity ) : G(_G), s(_s), t(_t), flow(_G, 0), capacity(_capacity), cut(_G, false) { 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; /* 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.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 ( !what_heur && !end && k > 0 ) { b=k; end=true; } else break; } if ( active[b] == 0 ) --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.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; } 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; } 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 //unlacing starts 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; } } //unlacing ends //gapping starts 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; //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 != 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; } } } // if ( exc > 0 ) } // if stack[b] is nonempty } // while(true) for( EachNodeIt v=G.template first(); v.valid(); ++v) if (level.get(v) >= n ) cut.set(v,true); value = excess.get(t); /*Max flow value.*/ } //void run() T maxFlow() { return value; } CutMap minCut() { return cut; } }; }//namespace #endif