jacint@78: /* jacint@78: preflow_push_max_flow_h jacint@78: by jacint. jacint@78: Runs a preflow push algorithm with the modification, jacint@78: that we do not push on Nodes with level at least n. jacint@78: 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@78: NodeMap mincut(): returns a jacint@78: characteristic vector of a minimum cut. jacint@78: */ jacint@78: jacint@78: #ifndef PREFLOW_PUSH_MAX_FLOW_H jacint@78: #define PREFLOW_PUSH_MAX_FLOW_H jacint@78: jacint@78: #include jacint@78: #include jacint@78: #include jacint@78: jacint@78: #include jacint@78: #include jacint@78: jacint@78: jacint@78: namespace marci { jacint@78: jacint@78: template 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@78: typename Graph::EdgeMap& capacity; jacint@78: T value; jacint@78: typename Graph::NodeMap mincutvector; jacint@78: jacint@78: jacint@78: jacint@78: public: jacint@78: jacint@78: 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) { } jacint@78: jacint@78: jacint@78: /* jacint@78: The run() function runs a modified version of the 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@78: typename Graph::EdgeMap flow(G, 0); //the flow value, 0 everywhere jacint@78: typename Graph::NodeMap level(G); //level of Node jacint@78: typename Graph::NodeMap excess(G); //excess of Node jacint@78: jacint@78: int n=G.nodeNum(); //number of Nodes jacint@78: int b=n-2; jacint@78: /*b is a bound on the highest level of an active Node. In the beginning it is at most n-2.*/ jacint@78: jacint@78: std::vector numb(n); //The number of Nodes on level i < n. jacint@78: jacint@78: std::vector > stack(2*n-1); //Stack of the active Nodes in level i. jacint@78: jacint@78: jacint@78: jacint@78: /*Reverse_bfs from t, to find the starting level.*/ jacint@78: jacint@78: reverse_bfs bfs(G, t); jacint@78: bfs.run(); jacint@78: for(EachNodeIt v=G.template first(); v.valid(); ++v) jacint@78: { jacint@78: int dist=bfs.dist(v); jacint@78: level.set(v, dist); jacint@78: ++numb[dist]; jacint@78: } jacint@78: jacint@78: /*The level of s is fixed to n*/ jacint@78: level.set(s,n); jacint@78: jacint@78: jacint@78: /* Starting flow. It is everywhere 0 at the moment. */ jacint@78: jacint@78: for(OutEdgeIt i=G.template first(s); i.valid(); ++i) jacint@78: { jacint@78: NodeIt w=G.head(i); jacint@78: flow.set(i, capacity.get(i)); jacint@78: stack[bfs.dist(w)].push(w); jacint@78: excess.set(w, capacity.get(i)); jacint@78: } jacint@78: jacint@78: jacint@78: /* jacint@78: End of preprocessing jacint@78: */ jacint@78: jacint@78: jacint@78: jacint@78: jacint@78: /* jacint@78: Push/relabel on the highest level active Nodes. jacint@78: */ jacint@78: jacint@78: /*While there exists an active Node.*/ jacint@78: while (b) { jacint@78: jacint@78: /*We decrease the bound if there is no active Node of level b.*/ jacint@78: if (stack[b].empty()) { jacint@78: --b; jacint@78: } else { jacint@78: jacint@78: NodeIt w=stack[b].top(); //w is the highest label active Node. jacint@78: stack[b].pop(); //We delete w from the stack. jacint@78: jacint@78: int newlevel=2*n-2; //In newlevel we maintain the next level of w. jacint@78: jacint@78: for(OutEdgeIt e=G.template first(w); e.valid(); ++e) { jacint@78: NodeIt v=G.head(e); jacint@78: /*e is the Edge wv.*/ jacint@78: jacint@78: if (flow.get(e) excess.get(w)) { jacint@78: /*A nonsaturating push.*/ jacint@78: jacint@78: if (excess.get(v)==0 && v != s) stack[level.get(v)].push(v); jacint@78: /*v becomes active.*/ jacint@78: jacint@78: flow.set(e, flow.get(e)+excess.get(w)); jacint@78: excess.set(v, excess.get(v)+excess.get(w)); jacint@78: excess.set(w,0); jacint@78: //std::cout << w << " " << v <<" elore elen nonsat pump " << std::endl; jacint@78: break; jacint@78: } else { jacint@78: /*A saturating push.*/ jacint@78: jacint@78: if (excess.get(v)==0 && v != s) stack[level.get(v)].push(v); jacint@78: /*v becomes active.*/ jacint@78: jacint@78: excess.set(v, excess.get(v)+capacity.get(e)-flow.get(e)); jacint@78: excess.set(w, excess.get(w)-capacity.get(e)+flow.get(e)); jacint@78: flow.set(e, capacity.get(e)); jacint@78: //std::cout << w <<" " << v <<" elore elen sat pump " << std::endl; jacint@78: if (excess.get(w)==0) break; jacint@78: /*If w is not active any more, then we go on to the next Node.*/ jacint@78: jacint@78: } // if (capacity.get(e)-flow.get(e) > excess.get(w)) jacint@78: } // if (level.get(w)==level.get(v)+1) jacint@78: jacint@78: else {newlevel = newlevel < level.get(v) ? newlevel : level.get(v);} jacint@78: jacint@78: } //if (flow.get(e)(w); e.valid(); ++e) { jacint@78: NodeIt v=G.tail(e); jacint@78: /*e is the Edge vw.*/ jacint@78: jacint@78: if (excess.get(w)==0) break; jacint@78: /*It may happen, that w became inactive in the first 'for' cycle.*/ jacint@78: jacint@78: if(flow.get(e)>0) { jacint@78: /*e is an Edge of the residual graph */ jacint@78: jacint@78: if(level.get(w)==level.get(v)+1) { jacint@78: /*Push is allowed now*/ jacint@78: jacint@78: if (flow.get(e) > excess.get(w)) { jacint@78: /*A nonsaturating push.*/ jacint@78: jacint@78: if (excess.get(v)==0 && v != s) stack[level.get(v)].push(v); jacint@78: /*v becomes active.*/ jacint@78: jacint@78: flow.set(e, flow.get(e)-excess.get(w)); jacint@78: excess.set(v, excess.get(v)+excess.get(w)); jacint@78: excess.set(w,0); jacint@78: //std::cout << v << " " << w << " vissza elen nonsat pump " << std::endl; jacint@78: break; jacint@78: } else { jacint@78: /*A saturating push.*/ jacint@78: jacint@78: if (excess.get(v)==0 && v != s) stack[level.get(v)].push(v); jacint@78: /*v becomes active.*/ jacint@78: jacint@78: flow.set(e,0); jacint@78: excess.set(v, excess.get(v)+flow.get(e)); jacint@78: excess.set(w, excess.get(w)-flow.get(e)); jacint@78: //std::cout << v <<" " << w << " vissza elen sat pump " << std::endl; jacint@78: if (excess.get(w)==0) { break;} jacint@78: } //if (flow.get(e) > excess.get(v)) jacint@78: } //if(level.get(w)==level.get(v)+1) jacint@78: jacint@78: else {newlevel = newlevel < level.get(v) ? newlevel : level.get(v);} jacint@78: //std::cout << "Leveldecrease of Node " << w << " to " << newlevel << std::endl; jacint@78: jacint@78: } //if (flow.get(e)>0) jacint@78: jacint@78: } //for in-Edge jacint@78: jacint@78: jacint@78: jacint@78: jacint@78: /* jacint@78: Relabel jacint@78: */ jacint@78: if (excess.get(w)>0) { jacint@78: /*Now newlevel <= n*/ jacint@78: jacint@78: int l=level.get(w); //l is the old level of w. jacint@78: --numb[l]; jacint@78: jacint@78: if (newlevel == n) { jacint@78: level.set(w,n); jacint@78: jacint@78: } else { jacint@78: jacint@78: if (numb[l]) { jacint@78: /*If the level of w remains nonempty.*/ jacint@78: jacint@78: level.set(w,++newlevel); jacint@78: ++numb[newlevel]; jacint@78: stack[newlevel].push(w); jacint@78: b=newlevel; jacint@78: } else { jacint@78: /*If the level of w gets empty.*/ jacint@78: jacint@78: for (EachNodeIt v=G.template first(); v.valid() ; ++v) { jacint@78: if (level.get(v) >= l ) { jacint@78: level.set(v,n); jacint@78: } jacint@78: } jacint@78: jacint@78: for (int i=l+1 ; i!=n ; ++i) numb[i]=0; jacint@78: } //if (numb[l]) jacint@78: jacint@78: } // if (newlevel = n) jacint@78: jacint@78: } // if (excess.get(w)>0) jacint@78: jacint@78: jacint@78: } //else jacint@78: jacint@78: } //while(b) jacint@78: jacint@78: value=excess.get(t); jacint@78: /*Max flow value.*/ jacint@78: jacint@78: jacint@78: jacint@78: /* jacint@78: We find an empty level, e. The Nodes above this level give jacint@78: a minimum cut. jacint@78: */ jacint@78: jacint@78: int e=1; jacint@78: jacint@78: while(e) { jacint@78: if(numb[e]) ++e; jacint@78: else break; jacint@78: } jacint@78: for (EachNodeIt v=G.template first(); v.valid(); ++v) { jacint@78: if (level.get(v) > e) mincutvector.set(v, true); jacint@78: } 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@78: */ jacint@78: jacint@78: typename Graph::NodeMap mincut() { jacint@78: return mincutvector; jacint@78: } jacint@78: jacint@78: jacint@78: }; jacint@78: }//namespace marci jacint@78: #endif jacint@78: jacint@78: jacint@78: jacint@78: jacint@78: