Grafalgo
Library of useful data structures and algorithms
|
00001 #include "lcap.h" 00002 00003 using namespace grafalgo; 00004 00005 lcap::lcap(Wflograph& wfg1, flow& flowVal, floCost& flowCost, bool mostNeg) : wfg(&wfg1) { 00006 // Find minimum cost, flow in wfg using the least-cost augmenting path 00007 // algorithm. If the mostNeg flag is true, the algorithm finds a 00008 // flow with the largest negative cost. Otherwise, it finds a min 00009 // cost, max flow. Returns flow value in floVal and cost in floCost. 00010 00011 lab = new int[wfg->n()+1]; 00012 pEdge = new edge[wfg->n()+1]; 00013 00014 initLabels(); 00015 flowVal = flowCost = 0; 00016 while (findpath()) { 00017 flow nuFlo; floCost pathCost; 00018 pathRcapCost(nuFlo,pathCost); 00019 if (mostNeg && pathCost >= 0) break; 00020 augment(nuFlo); 00021 flowVal += nuFlo; flowCost += nuFlo*pathCost; 00022 } 00023 delete [] lab; delete [] pEdge; 00024 } 00025 00026 00027 void lcap::initLabels() { 00028 // Compute values for labels that give non-negative transformed costs. 00029 // The labels are the least cost path distances from an imaginary 00030 // vertex with a length 0 edge to every vertex in the graph. 00031 // Uses the breadth-first scanning algorithm to compute shortest 00032 // paths. 00033 int pass; 00034 vertex u, v,last; edge e; 00035 List q(wfg->n()); 00036 00037 for (u = 1; u <= wfg->n(); u++) { 00038 pEdge[u] = 0; lab[u] = 0; q.addLast(u); 00039 } 00040 pass = 0; last = q.last(); 00041 while (!q.empty()) { 00042 u = q.first(); q.removeFirst(); 00043 for (e = wfg->firstAt(u); e != 0; e = wfg->nextAt(u,e)) { 00044 v = wfg->head(e); 00045 if (v == u) continue; 00046 if (lab[v] > lab[u] + wfg->cost(u,e)) { 00047 lab[v] = lab[u] + wfg->cost(u,e); pEdge[v] = e; 00048 if (!q.member(v)) q.addLast(v); 00049 } 00050 } 00051 if (u == last && !q.empty()) { pass++; last = q.last(); } 00052 if (pass == wfg->n()) 00053 Util::fatal("initLabels: negative cost cycle"); 00054 } 00055 } 00056 00057 bool lcap::findpath() { 00058 // Find a least cost augmenting path. 00059 vertex u,v; edge e; 00060 int c[wfg->n()+1]; Dheap S(wfg->n(),4); 00061 00062 for (u = 1; u <= wfg->n(); u++) { pEdge[u] = 0; c[u] = Util::BIGINT32; } 00063 c[wfg->src()] = 0; S.insert(wfg->src(),0); 00064 while (!S.empty()) { 00065 u = S.deletemin(); 00066 for (e = wfg->firstAt(u); e != 0; e = wfg->nextAt(u,e)) { 00067 if (wfg->res(u,e) == 0) continue; 00068 v = wfg->mate(u,e); 00069 if (c[v] > c[u] + wfg->cost(u,e) + (lab[u] - lab[v])) { 00070 pEdge[v] = e; 00071 c[v] = c[u] + wfg->cost(u,e) + (lab[u] - lab[v]); 00072 if (!S.member(v)) S.insert(v,c[v]); 00073 else S.changekey(v,c[v]); 00074 } 00075 } 00076 } 00077 // update labels for next round 00078 for (u = 1; u <= wfg->n(); u++) lab[u] += c[u]; 00079 return (pEdge[wfg->snk()] != 0 ? true : false); 00080 } 00081 00082 void lcap::pathRcapCost(flow& rcap, floCost& pc) { 00083 // Return the residual capacity and cost of the path defined by pEdge 00084 // in rcap and pc. 00085 vertex u, v; edge e; 00086 00087 rcap = Util::BIGINT32; pc = 0; 00088 u = wfg->snk(); e = pEdge[u]; 00089 while (u != wfg->src()) { 00090 v = wfg->mate(u,e); 00091 rcap = min(rcap,wfg->res(v,e)); pc += wfg->cost(v,e); 00092 u = v; e = pEdge[u]; 00093 } 00094 } 00095 00096 void lcap::augment(flow& f) { 00097 // Add f units of flow to the path defined by pEdge. 00098 vertex u, v; edge e; 00099 00100 u = wfg->snk(); e = pEdge[u]; 00101 while (u != wfg->src()) { 00102 v = wfg->mate(u,e); 00103 wfg->addFlow(v,e,f); 00104 u = v; e = pEdge[u]; 00105 } 00106 }