Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/graphAlgorithms/maxFlo/prePush.cpp
00001 #include "prePush.h"
00002 
00003 prePush::prePush(Flograph& fg1, int& floVal) : fg(&fg1) {
00004 // Find maximum flow in fg using the preflow-push method.
00005 // The base clase constructor initializes data used by all
00006 // variants.
00007 
00008         excess = new int[fg->n()+1];
00009         nextedge = new edge[fg->n()+1];
00010 
00011         // initialization
00012         for (vertex u = 1; u <= fg->n(); u++) {
00013                 nextedge[u] = fg->firstAt(u); excess[u] = 0;
00014         }
00015         vertex s = fg->src();
00016         for (edge e = fg->firstOut(s); e != 0; e = fg->nextAt(s,e)) {
00017                 vertex v = fg->head(e);
00018                 fg->addFlow(s,e,fg->cap(s,e));
00019                 if (v != fg->snk()) excess[v] = fg->cap(s,e);
00020         }
00021         d = new int[fg->n()+1];
00022         satCount = nonSatCount = newDistCount = relabCount = 0;
00023         initdist();
00024         // constructor of derived class takes over from here
00025 }
00026 
00027 prePush::~prePush() { delete [] d; delete [] excess; delete [] nextedge; }
00028 
00029 void prePush::newUnbal(vertex u) {
00030         Util::fatal("prePush::newUnbal: execution should never reach here");
00031 }
00032 
00033 bool prePush::balance(vertex u) {
00034 // Attempt to balance vertex u, by pushing flow through admissible edges.
00035         if (excess[u] <= 0) return true;
00036         while (true) {
00037                 edge e = nextedge[u];
00038                 if (e == 0) return false; 
00039                 vertex v = fg->mate(u,e);
00040                 if (fg->res(u,e) > 0 && d[u] == d[v]+1 && nextedge[v] != 0) {
00041                         flow x = min(excess[u],fg->res(u,e));
00042                         if (x == fg->res(u,e)) satCount++;
00043                         else nonSatCount++;
00044                         fg->addFlow(u,e,x);
00045                         excess[u] -= x; excess[v] += x;
00046                         if (v != fg->src() && v != fg->snk()) newUnbal(v);
00047                         if (excess[u] <= 0) return true;
00048                 }
00049                 nextedge[u] = fg->nextAt(u,e);
00050         }
00051 }
00052 
00053 void prePush::initdist() {
00054 // Compute exact distance labels and return in d.
00055 // For vertices that can't reach t, compute labels to s.
00056         vertex u,v; edge e;
00057         List queue(fg->n());
00058 
00059         newDistCount++;
00060         for (u = 1; u < fg->n(); u++) d[u] = 2*fg->n();
00061 
00062         // compute distance labels for vertices that have path to sink
00063         d[fg->snk()] = 0;
00064         queue.addLast(fg->snk());
00065         while (!queue.empty()) {
00066                 u = queue.first(); queue.removeFirst();
00067                 for (e = fg->firstAt(u); e != 0; e = fg->nextAt(u,e)) {
00068                         v = fg->mate(u,e);
00069                         if (fg->res(v,e) > 0 && d[v] > d[u] + 1) {
00070                                 d[v] = d[u] + 1;
00071                                 queue.addLast(v);
00072                         }
00073                 }
00074         }
00075 
00076         if (d[fg->src()] < fg->n()) 
00077                 Util::fatal("initdist: path present from source to sink");
00078 
00079         // compute distance labels for remaining vertices
00080         d[fg->src()] = fg->n();
00081         queue.addLast(fg->src());
00082         while (!queue.empty()) {
00083                 u = queue.first(); queue.removeFirst();
00084                 for (e = fg->firstAt(u); e != 0; e = fg->nextAt(u,e)) {
00085                         v = fg->mate(u,e);
00086                         if (fg->res(v,e) > 0 && d[v] > d[u] + 1) {
00087                                 d[v] = d[u] + 1;
00088                                 queue.addLast(v);
00089                         }
00090                 }
00091         }
00092 }
00093 
00094 int prePush::minlabel(vertex u) {
00095 // Find smallest label on a vertex adjacent to v through an edge with
00096 // positive residual capacity.
00097         int small; edge e;
00098 
00099         small = 2*fg->n();
00100         for (e = fg->firstAt(u); e != 0; e = fg->nextAt(u,e))
00101                 if (fg->res(u,e) > 0)
00102                         small = min(small,d[fg->mate(u,e)]);
00103         return small;
00104 }
00105 
00106 int prePush::flowValue() {
00107 // Return the value of the flow leaving the source.
00108         int fv = 0; vertex s = fg->src();
00109         for (edge e = fg->firstAt(s); e != 0; e = fg->nextAt(s,e))
00110                 fv += fg->f(s,e);
00111         return fv;
00112 }
 All Classes Files Functions Variables Typedefs Friends