Grafalgo
Library of useful data structures and algorithms
|
00001 // WORK IN PROGRESS - convert to implement the scaling algorithm 00002 // Coding started, but not yet complete. 00003 00004 // usage: scale 00005 // 00006 // Scale reads a Wflograph from stdin, and computes a minimum cost 00007 // maximum flow between vertices 1 and n using the scaling algorithm 00008 // 00009 // This program is not bullet-proof. Caveat emptor. 00010 00011 #include "stdinc.h" 00012 #include "Wflograph.h" 00013 #include "List.h" 00014 #include "Dheap.h" 00015 #include "dinic.h" 00016 00017 using namespace grafalgo; 00018 00019 void scale(flograph&); 00020 void initLabels(flograph&, int*); 00021 void findpath(flograph&, int*, list&); 00022 00023 int main() { 00024 Wflograph wfg; cin >> wfg; 00025 lcap(wfg); cout << wfg; 00026 } 00027 00028 class scale { 00029 flograph* wfg; // graph we're finding flow on 00030 int* lab; // lab[u]=distance label for transformed costs 00031 int* excess; // excess[u]=excess flow entering u 00032 list* slist; // Source vertices 00033 list* tlist; // Sink vertices 00034 int Delta; // Current scaling factor 00035 vertex cs; // current source vertex 00036 00037 int findpath(vertex,list&); // find augmenting path 00038 void augment(list&); // add flow to augmenting path 00039 int newphase(); // prepare for a new phase 00040 int initLabels(); // assign initial values to labels 00041 public: scale(flograph*); // main program 00042 }; 00043 00044 scale::scale(flograph& wfg1) { 00045 void scale(flograph& wfg) { 00046 // Find minimum cost maximum flow in wfg using the scaling algorithm. 00047 // Assumes that the original graph has no negative cost cycles. 00048 int flo; 00049 00050 vertex u; edge e; 00051 flow maxcap; 00052 list p(wfg.m); 00053 00054 wfg = &wfg1; 00055 lab = new int[wfg.n+1]; excess = new int[wfg.n+1]; 00056 slist = new List(wfg.n); tlist = new List(wfg.n); 00057 00058 for (u = 1; u <= wfg.n; u++) lab[u] = excess[u] = 0; 00059 00060 // Initialize scaling factor 00061 maxcap = 0; 00062 for (e = 1; e <= wfg.m; e++) 00063 maxcap = max(maxcap,wfg.cap(wfg.tail(e),e)); 00064 for (Delta = 1; 2*Delta <= maxcap; Delta <<= 1) {} 00065 00066 // Determine a max flow so that we can initialize excess 00067 // values at s and t 00068 dinic(wfg,flo); 00069 for (e = wfg->firstAt(1); e != 0; e = wfg->nextAt(1,e)) 00070 excess[1] += wfg->f(1,e); 00071 excess[wfg->n] = -excess[1]; 00072 for (e = wfg->firstAt(1); e != 0; e = wfg->nextAt(1,e)) { 00073 u = wfg->tail(e); wfg->addflow(u,e,-(wfg->f(u,e))); 00074 } 00075 00076 initLabels(); 00077 00078 while (newphase()) { 00079 while (findpath(u,p)) { 00080 augment(p); 00081 } 00082 Delta /= 2; 00083 } 00084 delete [] lab; delete [] excess; 00085 delete slist; delete tlist; 00086 } 00087 00088 void initLabels() { 00089 // Compute values for labels that give non-negative transformed costs. 00090 // The labels are the least cost path distances from an imaginary 00091 // vertex with a length 0 edge to every vertex in the graph. 00092 // Uses the breadth-first scanning algorithm to compute shortest 00093 // paths. 00094 int pass; 00095 vertex v, w,last; edge e; 00096 vertex *p = new vertex[wfg.n+1]; 00097 List q(wfg.n); 00098 00099 for (v = 1; v <= wfg.n; v++) { 00100 p[v] = 0; lab[v] = 0; q &= v; 00101 } 00102 00103 pass = 0; last = wfg.n; 00104 00105 while (!empty()) { 00106 v = q.first(); q.removeFirst(); 00107 for (e = wfg.firstAt(v); e != 0; e = wfg.nextAt(v,e)) { 00108 w = wfg.head(e); 00109 if (w == v) continue; 00110 if (lab[w] > lab[v] + wfg.cost(v,e)) { 00111 lab[w] = lab[v] + wfg.cost(v,e); p[w] = v; 00112 if (!q.member(w)) q.addLast(w); 00113 } 00114 } 00115 if (v == last && !q.empty()) { pass++; last = q.last(); } 00116 if (pass == wfg.n) Util::fatal("initLabels: negative cost cycle"); 00117 } 00118 } 00119 00120 void newPhase() { 00121 // Do start of phase processing. 00122 00123 // identify unbalanced vertices 00124 slist.clear(); tlist.clear(); 00125 for (u = 2; u < wfg->n; u++) { 00126 if (excess[u] > 0) slist &= u; 00127 else if (excess[u] < 0) tlist &= u; 00128 } 00129 // Put source and sink at end of lists. 00130 slist &= 1; tlist &= wfg->n; 00131 00132 00133 // If any edge violates labeling condition, add Delta units of 00134 // flow to it. This eliminates it from the residual graph for 00135 // the current scaling factor. 00136 00137 vertex u,v; edge e; 00138 00139 for (e = 1; e <= wfg.m; e++) { 00140 u = wfg.tail(e); v = wfg.head(e); 00141 if (wfg.res(u,e) >= Delta) { 00142 if (wfg.cost(u,e) + lab[u] - lab[v] < 0) { 00143 wfg.addflow(u,e,Delta); 00144 excess[u] -= Delta; excess[v] += Delta; 00145 } 00146 } 00147 if (wfg.res(v,e) >= Delta) { 00148 if (wfg.cost(v,e) + lab[v] - lab[u] < 0) { 00149 wfg.addflow(v,e,Delta); 00150 excess[v] -= Delta; excess[u] += Delta; 00151 } 00152 } 00153 } 00154 } 00155 00156 00157 void findpath(flograph& wfg, int Delta, int* lab, list& p) { 00158 // Find a least cost augmenting path and update the labels. 00159 vertex u,v; edge e; 00160 edge *pathedge = new edge[wfg.n+1]; 00161 int *c = new int[wfg.n+1]; 00162 Dheap S(wfg.n,2); 00163 00164 for (u = 1; u <= wfg.n; u++) { pathedge[u] = 0; c[u] = BIGINT; } 00165 c[1] = 0; S.insert(1,0); 00166 while (!S.empty()) { 00167 u = S.deletemin(); 00168 for (e = wfg.first(u); e != 0; e = wfg.next(u,e)) { 00169 if (wfg.res(u,e) < Delta) continue; 00170 v = wfg.mate(u,e); 00171 if (c[v] > c[u] + wfg.cost(u,e) + (lab[u] - lab[v])) { 00172 pathedge[v] = e; 00173 c[v] = c[u] + wfg.cost(u,e) + (lab[u]-lab[v]); 00174 if (!S.member(v)) S.insert(v,c[v]); 00175 else S.changekey(v,c[v]); 00176 } 00177 } 00178 } 00179 p.clear(); 00180 for (u = wfg.n; pathedge[u] != 0; u = wfg.mate(u,pathedge[u])) { 00181 p.push(pathedge[u]); 00182 } 00183 for (u = 1; u <= wfg.n; u++) { 00184 lab[u] += c[u]; 00185 } 00186 delete [] pathedge; delete [] c; 00187 return; 00188 } 00189 00190 void augment(Wflograph& wfg,p) { 00191 // Augment the flow wfg along the path p. 00192 vertex u; edge e; 00193 00194 f = BIGINT; 00195 u = 1; 00196 for (e = p(1); e != 0; e = p.suc(e)) { 00197 f = min(f,wfg.res(u,e)); u = wfg.mate(u,e); 00198 } 00199 u = 1; 00200 for (e = p(1); e != 0; e = p.suc(e)) { 00201 wfg.addflow(u,e,f); u = wfg.mate(u,e); 00202 } 00203 return; 00204 } 00205