Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/graphAlgorithms/maxFlo/minFlow.cpp
00001 #include "minFlow.h"
00002 
00014 minFlow::minFlow(Mflograph& fg1, int& floVal) {
00015         pEdge = new edge[fg1.n()+1];
00016 
00017         // Create separate flow graph for use in first phase
00018         // Just like fg1, but with extra sink-to-source edge
00019         Mflograph fg2(fg1.n(),fg1.m()+1, fg1.src(), fg1.snk());
00020         fg2.copyFrom(fg1);
00021         int tcap = 0;
00022         for (edge e = fg2.first(); e != 0; e = fg2.next(e))
00023                 tcap += fg2.cap(fg2.tail(e),e);
00024         edge snkSrcEdge = fg2.join(fg2.snk(),fg2.src());
00025         if (snkSrcEdge == 0)
00026                 fatal("minFlow: internal error, can't create sink/source edge");
00027         fg2.setCapacity(snkSrcEdge,tcap); fg2.setMinFlo(snkSrcEdge,0);
00028         fg = &fg2;
00029 
00030         // attempt to find a flow that satisfies all min capacities
00031         // first, add edges with unsatisfied min capacities to a todo list
00032         UiList todo(fg->m());
00033         for (edge e = fg->first(); e != 0; e = fg->next(e)) {
00034                 vertex u = fg->tail(e);
00035                 if (fg->f(u,e) < fg->minFlo(e))
00036                         todo.addLast(e);
00037         }
00038         while (!todo.empty()) {
00039                 edge e = todo.first();
00040                 vertex u = fg->tail(e); vertex v = fg->head(e);
00041                 if (fg->f(u,e) >= fg->minFlo(e)) {
00042                         todo.removeFirst(); continue;
00043                 }
00044                 if (!findCycle(e)) { floVal = -1; return; }
00045                 add2cycle(e);
00046         }
00047         floVal = fg2.f(fg2.snk(),snkSrcEdge);
00048 
00049         // Transfer flow from fg2 to fg1
00050         fg2.remove(snkSrcEdge);
00051         fg1.copyFrom(fg2);
00052         fg = &fg1;
00053 
00054         // now, push additional flow from source to sink
00055         while(findPath()) {
00056                 floVal += augment(); 
00057         }
00058 }
00059 
00060 minFlow::~minFlow() { delete [] pEdge; }
00061 
00069 bool minFlow::findPath() {
00070         vertex u,v; edge e;
00071         UiList queue(fg->n());
00072 
00073         for (u = 1; u <= fg->n(); u++) pEdge[u] = 0;
00074         queue.addLast(fg->src());
00075         while (!queue.empty()) {
00076                 u = queue.first(); queue.removeFirst();
00077                 for (e = fg->firstAt(u); e != 0; e = fg->nextAt(u,e)) {
00078                         v = fg->mate(u,e);
00079                         if (fg->res(u,e) > 0 && pEdge[v] == 0 && 
00080                             v != fg->src()) {
00081                                 pEdge[v] = e;
00082                                 if (v == fg->snk()) return true;
00083                                 queue.addLast(v);
00084                         }
00085                 }
00086         }
00087         return false;
00088 }
00089 
00097 int minFlow::augment() {
00098         vertex u, v; edge e; flow f;
00099 
00100         // determine residual capacity of path
00101         f = BIGINT;
00102         u = fg->snk(); e = pEdge[u];
00103         while (u != fg->src()) {
00104                 v = fg->mate(u,e);
00105                 f = min(f,fg->res(v,e));
00106                 u = v; e = pEdge[u];
00107         }
00108         // add flow to saturate path
00109         u = fg->snk(); e = pEdge[u];
00110         while (u != fg->src()) {
00111                 v = fg->mate(u,e);
00112                 fg->addFlow(v,e,f);
00113                 u = v; e = pEdge[u];
00114         }
00115         return f;
00116 }
00117 
00128 bool minFlow::findCycle(edge e) {
00129         vertex u = fg->tail(e); vertex v = fg->head(e);
00130         for (vertex x = 1; x <= fg->n(); x++) pEdge[x] = 0;
00131 
00132         UiList queue(fg->n()); queue.addLast(v);
00133         while (!queue.empty()) {
00134                 vertex x = queue.first(); queue.removeFirst();
00135                 for (edge ex = fg->firstAt(x); ex != 0; ex = fg->nextAt(x,ex)) {
00136                         vertex y = fg->mate(x,ex);
00137                         if (fg->res(x,ex) > 0 && pEdge[y] == 0 && y != v) {
00138                                 pEdge[y] = ex;
00139                                 if (y == u) return true;
00140                                 queue.addLast(y);
00141                         }
00142                 }
00143         }
00144         return false;
00145 }
00146 
00153 int minFlow::add2cycle(edge e) {
00154         vertex u = fg->tail(e); vertex v = fg->head(e);
00155 
00156         // determine residual capacity of cycle
00157         flow f = fg->res(u,e);
00158         vertex x = u; edge px = pEdge[x];
00159         while (x != v) {
00160                 vertex y = fg->mate(x,px);
00161                 f = min(f,fg->res(y,px));
00162                 x = y; px = pEdge[x];
00163         }
00164         // add flow to saturate cycle
00165         fg->addFlow(u,e,f);
00166         x = u; px = pEdge[x];
00167         while (x != v) {
00168                 vertex y = fg->mate(x,px);
00169                 fg->addFlow(y,px,f);
00170                 x = y; px = pEdge[x];
00171         }
00172         return f;
00173 }
 All Classes Files Functions Variables Typedefs Friends