Grafalgo
Library of useful data structures and algorithms
|
00001 #include "dinicDtrees.h" 00002 00003 dinicDtrees::dinicDtrees(Flograph& fg1, int& floVal) : fg(&fg1) { 00004 level = new int[fg->n()+1]; nextEdge = new int[fg->n()+1]; 00005 upEdge = new int[fg->n()+1]; dt = new Dtrees(fg->n()); 00006 00007 for (vertex u = 1; u <= fg->n(); u++) { 00008 dt->addcost(u,Util::BIGINT32); 00009 level[u] = nextEdge[u] = upEdge[u] = 0; 00010 } 00011 00012 floVal = 0; 00013 while (newPhase()) { 00014 while (findPath()) floVal += augment(); 00015 } 00016 delete [] level; delete[] upEdge; delete [] nextEdge; delete dt; 00017 } 00018 00019 dinicDtrees::dinicDtrees(Flograph& fg1, int& floVal, string& stats) : fg(&fg1) { 00020 level = new int[fg->n()+1]; nextEdge = new int[fg->n()+1]; 00021 upEdge = new int[fg->n()+1]; dt = new Dtrees(fg->n()); 00022 00023 for (vertex u = 1; u <= fg->n(); u++) { 00024 dt->addcost(u,Util::BIGINT32); 00025 level[u] = nextEdge[u] = upEdge[u] = 0; 00026 } 00027 00028 floVal = 0; 00029 numPhase = numPaths = 0; avgPathLength = 0; phaseTime = pathTime = 0; 00030 uint32_t t1, t2, t3; 00031 t1 = Util::getTime(); 00032 while (newPhase()) { 00033 t2 = Util::getTime(); phaseTime += (t2-t1); 00034 numPhase++; 00035 while (findPath()) { 00036 t3 = Util::getTime(); pathTime += (t3-t2); 00037 numPaths++; avgPathLength += level[fg->snk()]; 00038 00039 floVal += augment(); 00040 t2 = Util::getTime(); 00041 } 00042 t3 = Util::getTime(); pathTime += (t3-t2); 00043 t1 = Util::getTime(); 00044 } 00045 t2 = Util::getTime(); phaseTime += (t2-t1); 00046 avgPathLength /= numPaths; 00047 stringstream ss; 00048 ss << numPhase << " " << numPaths << " " << avgPathLength 00049 << " " << phaseTime << " " << pathTime; 00050 stats = ss.str(); 00051 00052 delete [] level; delete[] upEdge; delete [] nextEdge; delete dt; 00053 } 00054 00055 bool dinicDtrees::findPath() { 00056 // Find an augmenting path. 00057 vertex u, v; edge e; 00058 00059 while (nextEdge[fg->src()] != 0) { 00060 u = dt->findroot(fg->src()); e = nextEdge[u]; 00061 while (1) { // look for forward path 00062 if (u == fg->snk()) return true; 00063 if (e == 0) { nextEdge[u] = 0; break; } 00064 v = fg->mate(u,e); 00065 if (fg->res(u,e) > 0 && level[v] == level[u] + 1 00066 && nextEdge[v] != 0) { 00067 dt->addcost(u,fg->res(u,e) - dt->nodeCost(u)); 00068 dt->link(u,v); upEdge[u] = e; 00069 nextEdge[u] = e; 00070 u = dt->findroot(fg->src()); e = nextEdge[u]; 00071 } else { 00072 e = fg->nextAt(u,e); 00073 } 00074 } 00075 // prune dead-end 00076 for (e = fg->firstAt(u); e != 0; e = fg->nextAt(u,e)) { 00077 v = fg->mate(u,e); 00078 if (u != dt->parent(v) || e != upEdge[v]) continue; 00079 dt->cut(v); upEdge[v] = 0; 00080 fg->addFlow(v,e, 00081 (fg->cap(v,e)-dt->nodeCost(v)) - fg->f(v,e)); 00082 dt->addcost(v,Util::BIGINT32 - dt->nodeCost(v)); 00083 } 00084 } 00085 return false; 00086 } 00087 00088 int dinicDtrees::augment() { 00089 // Add flow to the source-sink path defined by the path in the 00090 // dynamic trees data structure 00091 vertex u; edge e; 00092 00093 NodeCostPair p = dt->findcost(fg->src()); 00094 int flo = p.c; 00095 dt->addcost(fg->src(),-flo); 00096 for (p = dt->findcost(fg->src()); p.c==0; p = dt->findcost(fg->src())) { 00097 u = p.x; e = upEdge[u]; 00098 fg->addFlow(u,e,fg->cap(u,e) - fg->f(u,e)); 00099 dt->cut(u); 00100 dt->addcost(u,Util::BIGINT32); 00101 upEdge[u] = 0; 00102 } 00103 return flo; 00104 } 00105 00106 bool dinicDtrees::newPhase() { 00107 // Prepare for a new phase. Return the number of edges in the source/sink 00108 // path, or 0 if none exists. 00109 vertex u, v; edge e; 00110 List q(fg->n()); 00111 for (u = 1; u <= fg->n(); u++) { 00112 nextEdge[u] = fg->firstAt(u); 00113 if (dt->parent(u) != 0) { // cleanup from previous phase 00114 e = upEdge[u]; 00115 fg->addFlow(u,e, 00116 (fg->cap(u,e)-dt->nodeCost(u)) - fg->f(u,e)); 00117 dt->cut(u); 00118 dt->addcost(u,Util::BIGINT32 - dt->nodeCost(u)); 00119 upEdge[u] = 0; 00120 } 00121 level[u] = fg->n(); 00122 } 00123 q.addLast(fg->src()); level[fg->src()] = 0; 00124 while (!q.empty()) { 00125 u = q.first(); q.removeFirst(); 00126 for (e = fg->firstAt(u); e != 0; e = fg->nextAt(u,e)) { 00127 v = fg->mate(u,e); 00128 if (fg->res(u,e) > 0 && level[v] == fg->n()) { 00129 level[v] = level[u] + 1; q.addLast(v); 00130 if (v == fg->snk()) return true; 00131 } 00132 } 00133 } 00134 return false; 00135 }