Exemplo n.º 1
0
 internal Edge FindEdgeTo(Vertex v)
 {
     foreach(Edge e in forward)
         if(e.to == v)
             return e;
     return null;
 }
Exemplo n.º 2
0
 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;
 }
Exemplo n.º 3
0
 /// <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);
             }
 }
Exemplo n.º 4
0
        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;
        }