Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/graphAlgorithms/maxFlo/minFlowx.cpp
00001 #include "minFlow.h"
00002 
00012 minFlow::minFlow(Mflograph& fg1, int& floVal) : fg(&fg1) {
00013         pEdge = new edge[fg->n()+1];
00014 
00015         // attempt to find a flow that satisfies all min capacities
00016         // first, add edges with unsatisfied min capacities to a todo list
00017         UiList todo(fg->m());
00018         for (edge e = fg->first(); e != 0; e = fg->next(e)) {
00019                 vertex u = fg->tail(e);
00020                 if (fg->f(u,e) < fg->minFlo(e))
00021                         todo.addLast(e);
00022         }
00023         floVal = 0;
00024         while (!todo.empty()) {
00025                 edge e = todo.first();
00026                 vertex u = fg->tail(e); vertex v = fg->head(e);
00027                 if (fg->f(u,e) >= fg->minFlo(e)) {
00028                         todo.removeFirst(); continue;
00029                 }
00030                 if (!findCycle(e)) { floVal = -1; return; }
00031                 floVal += add2cycle(e);
00032         }
00033 
00034         // now, push additional flow from source to sink
00035         while(findPath()) {
00036                 floVal += augment(); 
00037         }
00038 }
00039 
00040 minFlow::~minFlow() { delete [] pEdge; }
00041 
00049 bool minFlow::findPath() {
00050         vertex u,v; edge e;
00051         UiList queue(fg->n());
00052 
00053         for (u = 1; u <= fg->n(); u++) pEdge[u] = 0;
00054         queue.addLast(fg->src());
00055         while (!queue.empty()) {
00056                 u = queue.first(); queue.removeFirst();
00057                 for (e = fg->firstAt(u); e != 0; e = fg->nextAt(u,e)) {
00058                         v = fg->mate(u,e);
00059                         if (fg->res(u,e) > 0 && pEdge[v] == 0 && 
00060                             v != fg->src()) {
00061                                 pEdge[v] = e;
00062                                 if (v == fg->snk()) return true;
00063                                 queue.addLast(v);
00064                         }
00065                 }
00066         }
00067         return false;
00068 }
00069 
00077 int minFlow::augment() {
00078         vertex u, v; edge e; flow f;
00079 
00080         // determine residual capacity of path
00081         f = BIGINT;
00082         u = fg->snk(); e = pEdge[u];
00083         while (u != fg->src()) {
00084                 v = fg->mate(u,e);
00085                 f = min(f,fg->res(v,e));
00086                 u = v; e = pEdge[u];
00087         }
00088         // add flow to saturate path
00089         u = fg->snk(); e = pEdge[u];
00090         while (u != fg->src()) {
00091                 v = fg->mate(u,e);
00092                 fg->addFlow(v,e,f);
00093                 u = v; e = pEdge[u];
00094         }
00095         return f;
00096 }
00097 
00109 bool minFlow::findCycle(edge e) {
00110         vertex u = fg->tail(e); vertex v = fg->head(e);
00111         for (vertex x = 1; x <= fg->n(); x++) pEdge[x] = 0;
00112 
00113         UiList queue(fg->n()); queue.addLast(v);
00114         while (!queue.empty()) {
00115                 vertex x = queue.first(); queue.removeFirst();
00116                 for (edge ex = fg->firstAt(x); ex != 0; ex = fg->nextAt(x,ex)) {
00117                         vertex y = fg->mate(x,ex);
00118                         if (fg->res(x,ex) > 0 && pEdge[y] == 0 && y != v) {
00119                                 pEdge[y] = ex;
00120                                 if (y == u) return true;
00121                                 queue.addLast(y);
00122                         }
00123                 }
00124                 // if search reaches sink, continue searching from source
00125                 if (x != fg->snk() || pEdge[fg->src()] != 0) continue;
00126                 pEdge[fg->src()] = -1; // special value to indicate src/snk link
00127                 if (u == fg->src()) return true;
00128                 x = fg->src();
00129                 for (edge ex = fg->firstAt(x); ex != 0; ex = fg->nextAt(x,ex)) {
00130                         vertex y = fg->mate(x,ex);
00131                         if (fg->res(x,ex) > 0 && pEdge[y] == 0 && y != v) {
00132                                 pEdge[y] = ex;
00133                                 if (y == u) return true;
00134                                 queue.addLast(y);
00135                         }
00136                 }
00137         }
00138         return false;
00139 }
00140 
00148 int minFlow::add2cycle(edge e) {
00149         vertex u = fg->tail(e); vertex v = fg->head(e);
00150 
00151         // determine residual capacity of cycle
00152         flow f = fg->res(u,e);
00153         vertex x = (pEdge[u] != -1 ? u : fg->snk());
00154         edge px = pEdge[x];
00155         while (x != v) {
00156                 vertex y = fg->mate(x,px);
00157                 f = min(f,fg->res(y,px));
00158                 x = (pEdge[y] != -1 ? y : fg->snk());
00159                 px = pEdge[x];
00160         }
00161         // add flow to saturate cycle
00162         fg->addFlow(u,e,f);
00163         x = (pEdge[u] != -1 ? u : fg->snk());
00164         px = pEdge[x];
00165         while (x != v) {
00166                 vertex y = fg->mate(x,px);
00167                 fg->addFlow(y,px,f);
00168                 x = (pEdge[y] != -1 ? y : fg->snk());
00169                 px = pEdge[x];
00170         }
00171         return f;
00172 }
 All Classes Files Functions Variables Typedefs Friends