// -*- C++ -*- //The same as preflow.h, using ResGraphWrapper #ifndef HUGO_PREFLOW_RES_H #define HUGO_PREFLOW_RES_H #define H0 20 #define H1 1 #include #include #include #include namespace hugo { template , typename FlowMap=typename Graph::template EdgeMap > class PreflowRes { typedef typename Graph::Node Node; typedef typename Graph::Edge Edge; typedef typename Graph::NodeIt NodeIt; typedef typename Graph::OutEdgeIt OutEdgeIt; typedef typename Graph::InEdgeIt InEdgeIt; const Graph& G; Node s; Node t; const CapMap& capacity; FlowMap& flow; T value; bool constzero; typedef ResGraphWrapper ResGW; typedef typename ResGW::OutEdgeIt ResOutEdgeIt; typedef typename ResGW::InEdgeIt ResInEdgeIt; typedef typename ResGW::Edge ResEdge; public: PreflowRes(Graph& _G, Node _s, Node _t, CapMap& _capacity, FlowMap& _flow, bool _constzero ) : G(_G), s(_s), t(_t), capacity(_capacity), flow(_flow), constzero(_constzero) {} void run() { ResGW res_graph(G, capacity, flow); value=0; //for the subsequent runs 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; /* 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::template NodeMap level(G,n); typename Graph::template NodeMap excess(G); std::vector active(n-1,INVALID); typename Graph::template NodeMap next(G,INVALID); //Stack of the active nodes in level i < n. //We use it in both phases. typename Graph::template NodeMap left(G,INVALID); typename Graph::template NodeMap right(G,INVALID); std::vector level_list(n,INVALID); /* List of the nodes in level i bfs_queue; bfs_queue.push(t); while (!bfs_queue.empty()) { Node v=bfs_queue.front(); bfs_queue.pop(); int l=level[v]+1; ResInEdgeIt e; for(res_graph.first(e,v); res_graph.valid(e); res_graph.next(e)) { Node w=res_graph.tail(e); if ( level[w] == n && w != s ) { bfs_queue.push(w); Node first=level_list[l]; if ( G.valid(first) ) left.set(first,w); right.set(w,first); level_list[l]=w; level.set(w, l); } } } if ( !constzero ) { /* Counting the excess */ NodeIt v; for(G.first(v); G.valid(v); G.next(v)) { T exc=0; InEdgeIt e; for(G.first(e,v); G.valid(e); G.next(e)) exc+=flow[e]; OutEdgeIt f; for(G.first(f,v); G.valid(f); G.next(f)) exc-=flow[f]; excess.set(v,exc); //putting the active nodes into the stack int lev=level[v]; if ( exc > 0 && lev < n ) { next.set(v,active[lev]); active[lev]=v; } } } //the starting flow ResOutEdgeIt e; for(res_graph.first(e,s); res_graph.valid(e); res_graph.next(e)) { Node w=res_graph.head(e); if ( level[w] < n ) { if ( excess[w] == 0 && w!=t ) { next.set(w,active[level[w]]); active[level[w]]=w; } T rem=res_graph.resCap(e); excess.set(w, excess[w]+rem); res_graph.augment(e, rem ); } } /* 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 { phase=1; level.set(s,0); std::queue bfs_queue; bfs_queue.push(s); while (!bfs_queue.empty()) { Node v=bfs_queue.front(); bfs_queue.pop(); int l=level[v]+1; ResInEdgeIt e; for(res_graph.first(e,v); res_graph.valid(e); res_graph.next(e)) { Node u=res_graph.tail(e); if ( level[u] >= n ) { bfs_queue.push(u); level.set(u, l); if ( excess[u] > 0 ) { next.set(u,active[l]); active[l]=u; } } } } b=n-2; } } if ( !G.valid(active[b]) ) --b; else { end=false; Node w=active[b]; active[b]=next[w]; int lev=level[w]; T exc=excess[w]; int newlevel=n; //bound on the next level of w ResOutEdgeIt e; for(res_graph.first(e,w); res_graph.valid(e); res_graph.next(e)) { Node v=res_graph.head(e); if( lev > level[v] ) { /*Push is allowed now*/ if ( excess[v]==0 && v!=t && v!=s ) { int lev_v=level[v]; next.set(v,active[lev_v]); active[lev_v]=v; } T remcap=res_graph.resCap(e); if ( remcap >= exc ) { /*A nonsaturating push.*/ res_graph.augment(e, exc); excess.set(v, excess[v]+exc); exc=0; break; } else { /*A saturating push.*/ res_graph.augment(e, remcap); excess.set(v, excess[v]+remcap); exc-=remcap; } } else if ( newlevel > level[v] ){ newlevel = level[v]; } } 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 starts Node right_n=right[w]; Node left_n=left[w]; if ( G.valid(right_n) ) { if ( G.valid(left_n) ) { right.set(left_n, right_n); left.set(right_n, left_n); } else { level_list[lev]=right_n; left.set(right_n, INVALID); } } else { if ( G.valid(left_n) ) { right.set(left_n, INVALID); } else { level_list[lev]=INVALID; } } //unlacing ends if ( !G.valid(level_list[lev]) ) { //gapping starts for (int i=lev; i!=k ; ) { Node v=level_list[++i]; while ( G.valid(v) ) { level.set(v,n); v=right[v]; } level_list[i]=INVALID; if ( !what_heur ) active[i]=INVALID; } 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; //now k=newlevel Node first=level_list[newlevel]; if ( G.valid(first) ) left.set(first,w); right.set(w,first); left.set(w,INVALID); 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[t]; /*Max flow value.*/ } //void run() /* Returns the maximum value of a flow. */ T flowValue() { return value; } FlowMap Flow() { return flow; } void Flow(FlowMap& _flow ) { NodeIt v; for(G.first(v) ; G.valid(v); G.next(v)) _flow.set(v,flow[v]); } /* Returns the minimum min cut, by a bfs from s in the residual graph. */ template void minMinCut(_CutMap& M) { std::queue queue; M.set(s,true); queue.push(s); while (!queue.empty()) { Node w=queue.front(); queue.pop(); OutEdgeIt e; for(G.first(e,w) ; G.valid(e); G.next(e)) { Node v=G.head(e); if (!M[v] && flow[e] < capacity[e] ) { queue.push(v); M.set(v, true); } } InEdgeIt f; for(G.first(f,w) ; G.valid(f); G.next(f)) { Node v=G.tail(f); if (!M[v] && flow[f] > 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()) { Node w=queue.front(); queue.pop(); InEdgeIt e; for(G.first(e,w) ; G.valid(e); G.next(e)) { Node v=G.tail(e); if (!M[v] && flow[e] < capacity[e] ) { queue.push(v); M.set(v, true); } } OutEdgeIt f; for(G.first(f,w) ; G.valid(f); G.next(f)) { Node v=G.head(f); if (!M[v] && flow[f] > 0 ) { queue.push(v); M.set(v, true); } } } NodeIt v; for(G.first(v) ; G.valid(v); G.next(v)) { M.set(v, !M[v]); } } template void minCut(CutMap& M) { minMinCut(M); } void resetTarget (Node _t) {t=_t;} void resetSource (Node _s) {s=_s;} void resetCap (CapMap _cap) {capacity=_cap;} void resetFlow (FlowMap _flow, bool _constzero) { flow=_flow; constzero=_constzero; } }; } //namespace hugo #endif //HUGO_PREFLOW_RES_H