Grafalgo
Library of useful data structures and algorithms
|
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 }