Grafalgo
Library of useful data structures and algorithms
|
00001 #include "minFlow.h" 00002 00012 minFlow::minFlow(Mflograph& fg1, int& floVal) : fg(&fg1) { 00013 pEdge = new edge[fg->n()+1]; 00014 00015 // attempt to find a flow that satisfies all min capacities 00016 // first, add edges with unsatisfied min capacities to a todo list 00017 UiList todo(fg->m()); 00018 for (edge e = fg->first(); e != 0; e = fg->next(e)) { 00019 vertex u = fg->tail(e); 00020 if (fg->f(u,e) < fg->minFlo(e)) 00021 todo.addLast(e); 00022 } 00023 floVal = 0; 00024 while (!todo.empty()) { 00025 edge e = todo.first(); 00026 vertex u = fg->tail(e); vertex v = fg->head(e); 00027 if (fg->f(u,e) >= fg->minFlo(e)) { 00028 todo.removeFirst(); continue; 00029 } 00030 if (!findCycle(e)) { floVal = -1; return; } 00031 floVal += add2cycle(e); 00032 } 00033 00034 // now, push additional flow from source to sink 00035 while(findPath()) { 00036 floVal += augment(); 00037 } 00038 } 00039 00040 minFlow::~minFlow() { delete [] pEdge; } 00041 00049 bool minFlow::findPath() { 00050 vertex u,v; edge e; 00051 UiList queue(fg->n()); 00052 00053 for (u = 1; u <= fg->n(); u++) pEdge[u] = 0; 00054 queue.addLast(fg->src()); 00055 while (!queue.empty()) { 00056 u = queue.first(); queue.removeFirst(); 00057 for (e = fg->firstAt(u); e != 0; e = fg->nextAt(u,e)) { 00058 v = fg->mate(u,e); 00059 if (fg->res(u,e) > 0 && pEdge[v] == 0 && 00060 v != fg->src()) { 00061 pEdge[v] = e; 00062 if (v == fg->snk()) return true; 00063 queue.addLast(v); 00064 } 00065 } 00066 } 00067 return false; 00068 } 00069 00077 int minFlow::augment() { 00078 vertex u, v; edge e; flow f; 00079 00080 // determine residual capacity of path 00081 f = BIGINT; 00082 u = fg->snk(); e = pEdge[u]; 00083 while (u != fg->src()) { 00084 v = fg->mate(u,e); 00085 f = min(f,fg->res(v,e)); 00086 u = v; e = pEdge[u]; 00087 } 00088 // add flow to saturate path 00089 u = fg->snk(); e = pEdge[u]; 00090 while (u != fg->src()) { 00091 v = fg->mate(u,e); 00092 fg->addFlow(v,e,f); 00093 u = v; e = pEdge[u]; 00094 } 00095 return f; 00096 } 00097 00109 bool minFlow::findCycle(edge e) { 00110 vertex u = fg->tail(e); vertex v = fg->head(e); 00111 for (vertex x = 1; x <= fg->n(); x++) pEdge[x] = 0; 00112 00113 UiList queue(fg->n()); queue.addLast(v); 00114 while (!queue.empty()) { 00115 vertex x = queue.first(); queue.removeFirst(); 00116 for (edge ex = fg->firstAt(x); ex != 0; ex = fg->nextAt(x,ex)) { 00117 vertex y = fg->mate(x,ex); 00118 if (fg->res(x,ex) > 0 && pEdge[y] == 0 && y != v) { 00119 pEdge[y] = ex; 00120 if (y == u) return true; 00121 queue.addLast(y); 00122 } 00123 } 00124 // if search reaches sink, continue searching from source 00125 if (x != fg->snk() || pEdge[fg->src()] != 0) continue; 00126 pEdge[fg->src()] = -1; // special value to indicate src/snk link 00127 if (u == fg->src()) return true; 00128 x = fg->src(); 00129 for (edge ex = fg->firstAt(x); ex != 0; ex = fg->nextAt(x,ex)) { 00130 vertex y = fg->mate(x,ex); 00131 if (fg->res(x,ex) > 0 && pEdge[y] == 0 && y != v) { 00132 pEdge[y] = ex; 00133 if (y == u) return true; 00134 queue.addLast(y); 00135 } 00136 } 00137 } 00138 return false; 00139 } 00140 00148 int minFlow::add2cycle(edge e) { 00149 vertex u = fg->tail(e); vertex v = fg->head(e); 00150 00151 // determine residual capacity of cycle 00152 flow f = fg->res(u,e); 00153 vertex x = (pEdge[u] != -1 ? u : fg->snk()); 00154 edge px = pEdge[x]; 00155 while (x != v) { 00156 vertex y = fg->mate(x,px); 00157 f = min(f,fg->res(y,px)); 00158 x = (pEdge[y] != -1 ? y : fg->snk()); 00159 px = pEdge[x]; 00160 } 00161 // add flow to saturate cycle 00162 fg->addFlow(u,e,f); 00163 x = (pEdge[u] != -1 ? u : fg->snk()); 00164 px = pEdge[x]; 00165 while (x != v) { 00166 vertex y = fg->mate(x,px); 00167 fg->addFlow(y,px,f); 00168 x = (pEdge[y] != -1 ? y : fg->snk()); 00169 px = pEdge[x]; 00170 } 00171 return f; 00172 }