internal Edge FindEdgeTo(Vertex v) { foreach(Edge e in forward) if(e.to == v) return e; return null; }
public Edge(Vertex from, Vertex to, int capacity, int flow, object extraInfo) { this.from = from; this.to = to; this.capacity = capacity; this.flow = flow; this.extraInfo = extraInfo; }
/// <summary> /// Finds all property value reachable with solid edges only /// </summary> /// <param name="v"></param> protected void FindGoodValues(Vertex v) { foreach(Edge e in v.forward) if (e.capacity > 1) if (visited[e.to.ID] == 0) { visited[e.to.ID] = 1; whiteVerticesCount++; if (e.to.PropertyValue != -1) goodEndValues.Add(e.to.PropertyValue); FindGoodValues(e.to); } }
public int FordFulkerson() { int flow = 0; // TODO: don't need to allocate so many, gauze the buffer size carefully to reduce its size int dmax = vertices.Count; int mincutValue; Vertex[] d = new Vertex[dmax]; int d1, d2; IEnumerator<Vertex> iter; ArrayList aMinCut = new ArrayList(); Vertex p; Edge tmpe; while(true) { iter = vertices.GetEnumerator(); while(iter.MoveNext()) iter.Current.back = null; source.back = source; d[0] = source; d1 = 0; d2 = 1; while(d1 != d2) { foreach(Edge e in d[d1].forward) if(e.flow < e.capacity) if(e.to.back == null) { e.to.back = d[d1]; e.to.backType = 1; d[d2] = e.to; d2 = (d2 + 1) % dmax; if(d2 == d1) { Console.WriteLine("FATAL ERROR: Buffer is not long enough"); } } foreach(Edge e in d[d1].backward) if(e.flow > 0) if(e.from.back == null) { e.from.back = d[d1]; e.from.backType = 2; d[d2] = e.from; d2 = (d2 + 1) % dmax; if(d2 == d1) { Console.WriteLine("FATAL ERROR: Buffer is not long enough"); } } d1++; // found a path, can stop now if(sink.back != null) break; } // done searching for path, now check whether we can increase the flow if(sink.back == null) break; flow++; p = sink; while(p != source) { if(p.backType == 1) { tmpe = p.back.FindEdgeTo(p); tmpe.flow++; } else { tmpe = p.FindEdgeTo(p.back); tmpe.flow--; } p = p.back; } } // now we can use the information stored in .back to find the mincut iter = vertices.GetEnumerator(); mincutValue = 0; while(iter.MoveNext()) { Vertex v = iter.Current; if(v.back != null) foreach(Edge e in v.forward) if(e.to.back == null) { aMinCut.Add(e); mincutValue += e.flow; } } mincut = new Edge[aMinCut.Count]; for(int i = 0; i < mincut.Length; i++) mincut[i] = (Edge)aMinCut[i]; // correctness check of output if(mincutValue != flow) Console.WriteLine("Mincut != flow"); iter = vertices.GetEnumerator(); int sum; while(iter.MoveNext()) { p = iter.Current; sum = 0; foreach(Edge e in p.forward) { if(e.capacity < e.flow) Console.WriteLine("flow > capacity"); sum += e.flow; } foreach(Edge e in p.backward) sum -= e.flow; if(p == source) { if(sum != flow) Console.WriteLine("flow from source is wrong"); } else if(p == sink) { if(sum != -flow) Console.WriteLine("flow to sink is wrong"); }else if(sum != 0) Console.WriteLine("flow in != flow out"); } return flow; }