Grafalgo
Library of useful data structures and algorithms
|
00001 #include "minFlow.h" 00002 00014 minFlow::minFlow(Mflograph& fg1, int& floVal) { 00015 pEdge = new edge[fg1.n()+1]; 00016 00017 // Create separate flow graph for use in first phase 00018 // Just like fg1, but with extra sink-to-source edge 00019 Mflograph fg2(fg1.n(),fg1.m()+1, fg1.src(), fg1.snk()); 00020 fg2.copyFrom(fg1); 00021 int tcap = 0; 00022 for (edge e = fg2.first(); e != 0; e = fg2.next(e)) 00023 tcap += fg2.cap(fg2.tail(e),e); 00024 edge snkSrcEdge = fg2.join(fg2.snk(),fg2.src()); 00025 if (snkSrcEdge == 0) 00026 fatal("minFlow: internal error, can't create sink/source edge"); 00027 fg2.setCapacity(snkSrcEdge,tcap); fg2.setMinFlo(snkSrcEdge,0); 00028 fg = &fg2; 00029 00030 // attempt to find a flow that satisfies all min capacities 00031 // first, add edges with unsatisfied min capacities to a todo list 00032 UiList todo(fg->m()); 00033 for (edge e = fg->first(); e != 0; e = fg->next(e)) { 00034 vertex u = fg->tail(e); 00035 if (fg->f(u,e) < fg->minFlo(e)) 00036 todo.addLast(e); 00037 } 00038 while (!todo.empty()) { 00039 edge e = todo.first(); 00040 vertex u = fg->tail(e); vertex v = fg->head(e); 00041 if (fg->f(u,e) >= fg->minFlo(e)) { 00042 todo.removeFirst(); continue; 00043 } 00044 if (!findCycle(e)) { floVal = -1; return; } 00045 add2cycle(e); 00046 } 00047 floVal = fg2.f(fg2.snk(),snkSrcEdge); 00048 00049 // Transfer flow from fg2 to fg1 00050 fg2.remove(snkSrcEdge); 00051 fg1.copyFrom(fg2); 00052 fg = &fg1; 00053 00054 // now, push additional flow from source to sink 00055 while(findPath()) { 00056 floVal += augment(); 00057 } 00058 } 00059 00060 minFlow::~minFlow() { delete [] pEdge; } 00061 00069 bool minFlow::findPath() { 00070 vertex u,v; edge e; 00071 UiList queue(fg->n()); 00072 00073 for (u = 1; u <= fg->n(); u++) pEdge[u] = 0; 00074 queue.addLast(fg->src()); 00075 while (!queue.empty()) { 00076 u = queue.first(); queue.removeFirst(); 00077 for (e = fg->firstAt(u); e != 0; e = fg->nextAt(u,e)) { 00078 v = fg->mate(u,e); 00079 if (fg->res(u,e) > 0 && pEdge[v] == 0 && 00080 v != fg->src()) { 00081 pEdge[v] = e; 00082 if (v == fg->snk()) return true; 00083 queue.addLast(v); 00084 } 00085 } 00086 } 00087 return false; 00088 } 00089 00097 int minFlow::augment() { 00098 vertex u, v; edge e; flow f; 00099 00100 // determine residual capacity of path 00101 f = BIGINT; 00102 u = fg->snk(); e = pEdge[u]; 00103 while (u != fg->src()) { 00104 v = fg->mate(u,e); 00105 f = min(f,fg->res(v,e)); 00106 u = v; e = pEdge[u]; 00107 } 00108 // add flow to saturate path 00109 u = fg->snk(); e = pEdge[u]; 00110 while (u != fg->src()) { 00111 v = fg->mate(u,e); 00112 fg->addFlow(v,e,f); 00113 u = v; e = pEdge[u]; 00114 } 00115 return f; 00116 } 00117 00128 bool minFlow::findCycle(edge e) { 00129 vertex u = fg->tail(e); vertex v = fg->head(e); 00130 for (vertex x = 1; x <= fg->n(); x++) pEdge[x] = 0; 00131 00132 UiList queue(fg->n()); queue.addLast(v); 00133 while (!queue.empty()) { 00134 vertex x = queue.first(); queue.removeFirst(); 00135 for (edge ex = fg->firstAt(x); ex != 0; ex = fg->nextAt(x,ex)) { 00136 vertex y = fg->mate(x,ex); 00137 if (fg->res(x,ex) > 0 && pEdge[y] == 0 && y != v) { 00138 pEdge[y] = ex; 00139 if (y == u) return true; 00140 queue.addLast(y); 00141 } 00142 } 00143 } 00144 return false; 00145 } 00146 00153 int minFlow::add2cycle(edge e) { 00154 vertex u = fg->tail(e); vertex v = fg->head(e); 00155 00156 // determine residual capacity of cycle 00157 flow f = fg->res(u,e); 00158 vertex x = u; edge px = pEdge[x]; 00159 while (x != v) { 00160 vertex y = fg->mate(x,px); 00161 f = min(f,fg->res(y,px)); 00162 x = y; px = pEdge[x]; 00163 } 00164 // add flow to saturate cycle 00165 fg->addFlow(u,e,f); 00166 x = u; px = pEdge[x]; 00167 while (x != v) { 00168 vertex y = fg->mate(x,px); 00169 fg->addFlow(y,px,f); 00170 x = y; px = pEdge[x]; 00171 } 00172 return f; 00173 }