public void ArgumentExceptionInAddEdge()
        {
            var fg = new FlowGraph(2);

            Assert.Throws <ArgumentException>(() => fg.AddEdge(0, 0, -1));
            Assert.Throws <ArgumentException>(() => fg.AddEdge(0, 0, 0, -1));
        }
        /// <summary>
        /// Berechnet zu einem Flussgraphen den Residual-Graphen.
        /// </summary>
        /// <typeparam name="T">Der Datentyp des Graphen.</typeparam>
        /// <param name="graph">Der Graph.</param>
        /// <returns>Der Residualgraph.</returns>
        public static FlowGraph <T> GetResidualGraph <T> (this FlowGraph <T> graph)
        {
            if (graph.Edges.Where(e => !e.Capacity.HasValue).Any())
            {
                throw new ArgumentException("In dem Graphen muss für jede Kante eine Kapazität definiert sein.");
            }

            // Sicherstellen, dass der Fluss bei allen Kanten initialisiert ist.
            foreach (Edge <T> e in graph.Edges.Where(e => !e.Flow.HasValue))
            {
                e.Flow = 0;
            }

            FlowGraph <T> residualGraph = new FlowGraph <T>(graph.Source.Value, graph.Target.Value, graph.Vertices.Select(v => v.Value), isDirected: true);

            foreach (Edge <T> e in graph.Edges)
            {
                if ((e.Capacity - e.Flow) > 0)
                {
                    residualGraph.AddEdge(e.From, e.To, capacity: e.Capacity.Value, flow: e.Capacity.Value - e.Flow.Value);
                }

                if (e.Flow > 0)
                {
                    residualGraph.AddEdge(e.To, e.From, capacity: e.Capacity.Value, flow: e.Flow.Value * (-1));
                }
            }

            return(residualGraph);
        }
        public void MaxFlowTwiceTest()
        {
            var fg = new FlowGraph(3);

            Assert.That(fg.AddEdge(0, 1, 1), Is.Zero);
            Assert.That(fg.AddEdge(0, 2, 1), Is.EqualTo(1));
            Assert.That(fg.AddEdge(1, 2, 1), Is.EqualTo(2));
            Assert.That(fg.MaxFlow(0, 2), Is.EqualTo(2));

            Assert.That(fg.GetEdge(0), Is.EqualTo(new FlowGraph.Edge(0, 1, 1, 1)));
            Assert.That(fg.GetEdge(1), Is.EqualTo(new FlowGraph.Edge(0, 2, 1, 1)));
            Assert.That(fg.GetEdge(2), Is.EqualTo(new FlowGraph.Edge(1, 2, 1, 1)));

            fg.ChangeEdge(0, 100, 10);
            Assert.That(fg.GetEdge(0), Is.EqualTo(new FlowGraph.Edge(0, 1, 100, 10)));

            Assert.That(fg.MaxFlow(0, 2), Is.Zero);
            Assert.That(fg.MaxFlow(0, 1), Is.EqualTo(90));

            Assert.That(fg.GetEdge(0), Is.EqualTo(new FlowGraph.Edge(0, 1, 100, 100)));
            Assert.That(fg.GetEdge(1), Is.EqualTo(new FlowGraph.Edge(0, 2, 1, 1)));
            Assert.That(fg.GetEdge(2), Is.EqualTo(new FlowGraph.Edge(1, 2, 1, 1)));

            Assert.That(fg.MaxFlow(2, 0), Is.EqualTo(2));

            Assert.That(fg.GetEdge(0), Is.EqualTo(new FlowGraph.Edge(0, 1, 100, 99)));
            Assert.That(fg.GetEdge(1), Is.EqualTo(new FlowGraph.Edge(0, 2, 1, 0)));
            Assert.That(fg.GetEdge(2), Is.EqualTo(new FlowGraph.Edge(1, 2, 1, 0)));
        }
Beispiel #4
0
        public static void Solve()
        {
            var(N, G, E) = Scanner.Scan <int, int, int>();
            if (G == 0)
            {
                Console.WriteLine(0); return;
            }
            var P  = Scanner.ScanEnumerable <int>().ToArray();
            var fg = new FlowGraph(N + 1);

            foreach (var p in P)
            {
                fg.AddEdge(p, N, 1);
            }
            for (var i = 0; i < E; i++)
            {
                var(a, b) = Scanner.Scan <int, int>();
                fg.AddEdge(a, b, 1);
                fg.AddEdge(b, a, 1);
            }

            var answer = fg.MaxFlow(0, N);

            Console.WriteLine(answer);
        }
        public void ArgumentOutOfRangeExceptionInChangeEdge([Values(-1, 3)] int v)
        {
            var fg = new FlowGraph(3);

            fg.AddEdge(0, 1, 100);
            fg.AddEdge(1, 2, 100);
            Assert.Throws <ArgumentOutOfRangeException>(() => fg.ChangeEdge(v, 100, 10));
        }
        public void ArgumentExceptionInChangeEdge([Values(-10, 100)] int newFlow)
        {
            var fg = new FlowGraph(3);

            fg.AddEdge(0, 1, 100);
            fg.AddEdge(1, 2, 100);
            Assert.Throws <ArgumentException>(() => fg.ChangeEdge(1, 10, newFlow));
        }
        public void ArgumentOutOfRangeExceptionInMaxFlow(int u, int v)
        {
            var fg = new FlowGraph(3);

            fg.AddEdge(0, 1, 100);
            fg.AddEdge(1, 2, 100);
            Assert.Throws <ArgumentOutOfRangeException>(() => fg.MaxFlow(u, v));
        }
        public void ArgumentOutOfRangeExceptionInAddEdgeAndGetEdge([Values(-1, 3)] int v)
        {
            var fg = new FlowGraph(3);

            Assert.Throws <ArgumentOutOfRangeException>(() => fg.AddEdge(v, 1, 10));
            Assert.Throws <ArgumentOutOfRangeException>(() => fg.AddEdge(0, v, 10));
            Assert.Throws <ArgumentOutOfRangeException>(() => fg.GetEdge(v));
        }
        public void ArgumentExceptionInMaxFlow()
        {
            var fg = new FlowGraph(3);

            fg.AddEdge(0, 1, 100);
            fg.AddEdge(1, 2, 100);
            Assert.Throws <ArgumentException>(() => fg.MaxFlow(0, 0));
            Assert.Throws <ArgumentException>(() => fg.MaxFlow(0, 0, 0));
        }
        public void MinCostFlowSameCostPathsTest()
        {
            var fg = new FlowGraph(3);

            Assert.That(fg.AddEdge(0, 1, 1, 1), Is.Zero);
            Assert.That(fg.AddEdge(1, 2, 1), Is.EqualTo(1));
            Assert.That(fg.AddEdge(0, 2, 2, 1), Is.EqualTo(2));
            var actual = fg.MinCostSlope(0, 2).ToArray();

            Assert.That(actual[0], Is.EqualTo((0, 0)));
            Assert.That(actual[1], Is.EqualTo((3, 3)));
        }
        public void MinCostFlowSelfLoopTest()
        {
            var fg = new FlowGraph(3);

            Assert.That(fg.AddEdge(0, 0, 100, 123), Is.Zero);
            Assert.That(fg.GetEdge(0), Is.EqualTo(new FlowGraph.Edge(0, 0, 100, 0, 123)));
        }
        public void MaxFlowSimpleTest()
        {
            var fg = new FlowGraph(4);

            Assert.That(fg.AddEdge(0, 1, 1), Is.Zero);
            Assert.That(fg.AddEdge(0, 2, 1), Is.EqualTo(1));
            Assert.That(fg.AddEdge(1, 3, 1), Is.EqualTo(2));
            Assert.That(fg.AddEdge(2, 3, 1), Is.EqualTo(3));
            Assert.That(fg.AddEdge(1, 2, 1), Is.EqualTo(4));
            Assert.That(fg.MaxFlow(0, 3), Is.EqualTo(2));

            Assert.That(fg.GetEdge(0), Is.EqualTo(new FlowGraph.Edge(0, 1, 1, 1)));
            Assert.That(fg.GetEdge(1), Is.EqualTo(new FlowGraph.Edge(0, 2, 1, 1)));
            Assert.That(fg.GetEdge(2), Is.EqualTo(new FlowGraph.Edge(1, 3, 1, 1)));
            Assert.That(fg.GetEdge(3), Is.EqualTo(new FlowGraph.Edge(2, 3, 1, 1)));
            Assert.That(fg.GetEdge(4), Is.EqualTo(new FlowGraph.Edge(1, 2, 1, 0)));
        }
        public void MaxFlowMinCutTest()
        {
            var fg = new FlowGraph(3);

            Assert.That(fg.AddEdge(0, 1, 2), Is.Zero);
            Assert.That(fg.AddEdge(1, 2, 1), Is.EqualTo(1));
            Assert.That(fg.MaxFlow(0, 2), Is.EqualTo(1));

            Assert.That(fg.GetEdge(0), Is.EqualTo(new FlowGraph.Edge(0, 1, 2, 1)));
            Assert.That(fg.GetEdge(1), Is.EqualTo(new FlowGraph.Edge(1, 2, 1, 1)));

            var minCut = fg.MinCut(0);

            Assert.That(minCut[0], Is.True);
            Assert.That(minCut[1], Is.True);
            Assert.That(minCut[2], Is.False);
        }
        public void MinCostFlowSimpleTest()
        {
            var fg = new FlowGraph(4);

            fg.AddEdge(0, 1, 1, 1);
            fg.AddEdge(0, 2, 1, 1);
            fg.AddEdge(1, 3, 1, 1);
            fg.AddEdge(2, 3, 1, 1);
            fg.AddEdge(1, 2, 1, 1);
            var actual = fg.MinCostSlope(0, 3, 10).ToArray();

            Assert.That(actual[0], Is.EqualTo((0, 0)));
            Assert.That(actual[1], Is.EqualTo((2, 4)));

            Assert.That(fg.GetEdge(0), Is.EqualTo(new FlowGraph.Edge(0, 1, 1, 1, 1)));
            Assert.That(fg.GetEdge(1), Is.EqualTo(new FlowGraph.Edge(0, 2, 1, 1, 1)));
            Assert.That(fg.GetEdge(2), Is.EqualTo(new FlowGraph.Edge(1, 3, 1, 1, 1)));
            Assert.That(fg.GetEdge(3), Is.EqualTo(new FlowGraph.Edge(2, 3, 1, 1, 1)));
            Assert.That(fg.GetEdge(4), Is.EqualTo(new FlowGraph.Edge(1, 2, 1, 0, 1)));
        }
Beispiel #15
0
        public static void Solve()
        {
            var NK = Console.ReadLine().Split(" ").Select(int.Parse).ToArray();

            var(N, K) = (NK[0], NK[1]);
            var A = new long[N][].Select(x =>
                                         Console.ReadLine().Split(" ").Select(long.Parse).ToArray())
                    .ToArray();
            var        fg  = new FlowGraph(N * 2 + 2);
            var        s   = N * 2;
            var        t   = N * 2 + 1;
            const long inf = (long)1e9;

            fg.AddEdge(s, t, N * K, inf);
            for (var i = 0; i < N; i++)
            {
                fg.AddEdge(s, i, K);
                fg.AddEdge(N + i, t, K);
            }

            for (var i = 0; i < N; i++)
            {
                for (var j = 0; j < N; j++)
                {
                    fg.AddEdge(i, N + j, 1, inf - A[i][j]);
                }
            }

            var result = fg.MinCostFlow(s, t, N * K);

            Console.WriteLine(inf * N * K - result.Item2);

            var G = new char[N][].Select(x => Enumerable.Repeat('.', N).ToArray()).ToArray();

            foreach (var edge in fg.GetEdges().Where(x => x.From != s && x.To != t && x.Flow != 0))
            {
                G[edge.From][edge.To - N] = 'X';
            }

            Console.WriteLine(string.Join("\n", G.Select(x => new string(x))));
        }
        public void UsageTest()
        {
            var fg = new FlowGraph(2);

            fg.AddEdge(0, 1, 1, 2);
            Assert.That(fg.MinCostFlow(0, 1), Is.EqualTo((1, 2)));

            fg = new FlowGraph(2);
            fg.AddEdge(0, 1, 1, 2);
            var actual = fg.MinCostSlope(0, 1).ToArray();

            Assert.That(actual[0], Is.EqualTo((0, 0)));
            Assert.That(actual[1], Is.EqualTo((1, 2)));
        }
        public void MaxFlowStressTest()
        {
            for (var ph = 0; ph < 10000; ph++)
            {
                var n = Utilities.RandomInteger(2, 20);
                var m = Utilities.RandomInteger(1, 100);
                var(s, t) = Utilities.RandomPair(0, n - 1);
                if (Utilities.RandomBool())
                {
                    (s, t) = (t, s);
                }

                var fg = new FlowGraph(n);
                for (var i = 0; i < m; i++)
                {
                    var u = Utilities.RandomInteger(0, n - 1);
                    var v = Utilities.RandomInteger(0, n - 1);
                    var c = Utilities.RandomInteger(0, 10000);
                    fg.AddEdge(u, v, c);
                }

                var flow   = fg.MaxFlow(s, t);
                var dual   = 0L;
                var minCut = fg.MinCut(s);
                var flows  = new long[n];
                foreach (var edge in fg.GetEdges())
                {
                    flows[edge.From] -= edge.Flow;
                    flows[edge.To]   += edge.Flow;
                    if (minCut[edge.From] && !minCut[edge.To])
                    {
                        dual += edge.Capacity;
                    }
                }

                Assert.That(dual, Is.EqualTo(flow));
                Assert.That(flows[s], Is.EqualTo(-flow));
                Assert.That(flows[t], Is.EqualTo(flow));

                for (var i = 0; i < n; i++)
                {
                    if (i == s || i == t)
                    {
                        continue;
                    }
                    Assert.That(flows[i], Is.Zero);
                }
            }
        }
        public void Copy_must_work()
        {
            Vertex<string> source = new Vertex<string>("s");
            Vertex<string> target = new Vertex<string>("t");

            FlowGraph<string> flowGraph = new FlowGraph<string>(source, target, new List<Vertex<string>>() { source, target });

            flowGraph.AddVertex("a");
            flowGraph.AddVertex("b");

            flowGraph.AddEdge("s", "a", 5, 2);
            flowGraph.AddEdge("s", "b", 8, 4);
            flowGraph.AddEdge("a", "b", 3, 0);
            flowGraph.AddEdge("a", "t", 4, 2);
            flowGraph.AddEdge("b", "t", 6, 4);

            FlowGraph<string> flowGraphCopy = flowGraph.Copy();

            Assert.IsFalse(ReferenceEquals(flowGraph.Vertices, flowGraphCopy.Vertices));
            Assert.IsFalse(ReferenceEquals(flowGraph.Edges, flowGraphCopy.Edges));

            Assert.IsFalse(ReferenceEquals(flowGraph.Vertices[0], flowGraphCopy.Vertices[0]));
            Assert.IsFalse(ReferenceEquals(flowGraph.Edges[0], flowGraphCopy.Edges[0]));
        }
        public void MaxFlowComplexTest()
        {
            var fg = new FlowGraph(2);

            Assert.That(fg.AddEdge(0, 1, 1), Is.Zero);
            Assert.That(fg.AddEdge(0, 1, 2), Is.EqualTo(1));
            Assert.That(fg.AddEdge(0, 1, 3), Is.EqualTo(2));
            Assert.That(fg.AddEdge(0, 1, 4), Is.EqualTo(3));
            Assert.That(fg.AddEdge(0, 1, 5), Is.EqualTo(4));
            Assert.That(fg.AddEdge(0, 0, 6), Is.EqualTo(5));
            Assert.That(fg.AddEdge(1, 1, 7), Is.EqualTo(6));
            Assert.That(fg.MaxFlow(0, 1), Is.EqualTo(15));

            Assert.That(fg.GetEdge(0), Is.EqualTo(new FlowGraph.Edge(0, 1, 1, 1)));
            Assert.That(fg.GetEdge(1), Is.EqualTo(new FlowGraph.Edge(0, 1, 2, 2)));
            Assert.That(fg.GetEdge(2), Is.EqualTo(new FlowGraph.Edge(0, 1, 3, 3)));
            Assert.That(fg.GetEdge(3), Is.EqualTo(new FlowGraph.Edge(0, 1, 4, 4)));
            Assert.That(fg.GetEdge(4), Is.EqualTo(new FlowGraph.Edge(0, 1, 5, 5)));

            var minCut = fg.MinCut(0);

            Assert.That(minCut[0], Is.True);
            Assert.That(minCut[1], Is.False);
        }
        public void FordFulkerson_must_work()
        {
            // Quelle und Senke erstellen.
            Vertex <string> source = new Vertex <string>("s");
            Vertex <string> target = new Vertex <string>("t");

            // alle weiteren Knoten des Graphens erstellen.
            Vertex <string> vA = new Vertex <string>("a");
            Vertex <string> vB = new Vertex <string>("b");
            Vertex <string> vC = new Vertex <string>("c");
            Vertex <string> vD = new Vertex <string>("d");

            // Den Graphen erstellen.
            FlowGraph <string> flowGraph = new FlowGraph <string>(source, target, new List <Vertex <string> >()
            {
                source, vA, vB, vC, vD, target
            });

            // Die Kanten des Graphens erstellen.
            flowGraph.AddEdge("s", "a", capacity: 5, flow: 5);
            flowGraph.AddEdge("s", "b", capacity: 7, flow: 3);
            flowGraph.AddEdge("a", "b", capacity: 7, flow: 3);
            flowGraph.AddEdge("a", "c", capacity: 4, flow: 2);
            flowGraph.AddEdge("b", "c", capacity: 3, flow: 3);
            flowGraph.AddEdge("b", "d", capacity: 3, flow: 3);
            flowGraph.AddEdge("c", "d", capacity: 4, flow: 0);
            flowGraph.AddEdge("c", "t", capacity: 5, flow: 5);
            flowGraph.AddEdge("d", "t", capacity: 6, flow: 3);

            FlowGraph <string> maxFlowGraph = flowGraph.FordFulkerson();

            // Die Flüsse über die Kanten überprüfen.
            Assert.AreEqual(5, maxFlowGraph.Edges[0].Flow);
            Assert.AreEqual(5, maxFlowGraph.Edges[1].Flow);
            Assert.AreEqual(1, maxFlowGraph.Edges[2].Flow);
            Assert.AreEqual(4, maxFlowGraph.Edges[3].Flow);
            Assert.AreEqual(3, maxFlowGraph.Edges[4].Flow);
            Assert.AreEqual(3, maxFlowGraph.Edges[5].Flow);
            Assert.AreEqual(2, maxFlowGraph.Edges[6].Flow);
            Assert.AreEqual(5, maxFlowGraph.Edges[7].Flow);
            Assert.AreEqual(5, maxFlowGraph.Edges[8].Flow);

            // Die Kantenflüsse für den nächsten Test auf 0 setzen.
            flowGraph.Edges.ForEach(e =>
            {
                e.Flow = 0;
            });

            maxFlowGraph = flowGraph.FordFulkerson();

            // Die Flüsse über die Kanten überprüfen.
            Assert.AreEqual(4, maxFlowGraph.Edges[0].Flow);
            Assert.AreEqual(6, maxFlowGraph.Edges[1].Flow);
            Assert.AreEqual(0, maxFlowGraph.Edges[2].Flow);
            Assert.AreEqual(4, maxFlowGraph.Edges[3].Flow);
            Assert.AreEqual(3, maxFlowGraph.Edges[4].Flow);
            Assert.AreEqual(3, maxFlowGraph.Edges[5].Flow);
            Assert.AreEqual(2, maxFlowGraph.Edges[6].Flow);
            Assert.AreEqual(5, maxFlowGraph.Edges[7].Flow);
            Assert.AreEqual(5, maxFlowGraph.Edges[8].Flow);
        }
        public void MinCostFlowStressTest()
        {
            for (var ph = 0; ph < 1000; ph++)
            {
                var n = Utilities.RandomInteger(2, 20);
                var m = Utilities.RandomInteger(1, 100);
                var(s, t) = Utilities.RandomPair(0, n - 1);
                if (Utilities.RandomBool())
                {
                    (s, t) = (t, s);
                }

                var mfg  = new FlowGraph(n);
                var mcfg = new FlowGraph(n);
                for (var i = 0; i < m; i++)
                {
                    var u    = Utilities.RandomInteger(0, n - 1);
                    var v    = Utilities.RandomInteger(0, n - 1);
                    var cap  = Utilities.RandomInteger(0, 10);
                    var cost = Utilities.RandomInteger(0, 10000);
                    mcfg.AddEdge(u, v, cap, cost);
                    mfg.AddEdge(u, v, cap);
                }

                var(flow, cost1) = mcfg.MinCostFlow(s, t);
                Assert.That(flow, Is.EqualTo(mfg.MaxFlow(s, t)));

                var cost2      = 0L;
                var capacities = new long[n];
                foreach (var edge in mcfg.GetEdges())
                {
                    capacities[edge.From] -= edge.Flow;
                    capacities[edge.To]   += edge.Flow;
                    cost2 += edge.Flow * edge.Cost;
                }

                Assert.That(cost1, Is.EqualTo(cost2));

                for (var i = 0; i < n; i++)
                {
                    if (i == s)
                    {
                        Assert.That(capacities[i], Is.EqualTo(-flow));
                    }
                    else if (i == t)
                    {
                        Assert.That(capacities[i], Is.EqualTo(flow));
                    }
                    else
                    {
                        Assert.That(capacities[i], Is.EqualTo(0));
                    }
                }

                Assert.DoesNotThrow(() =>
                {
                    var dist = new long[n];
                    while (true)
                    {
                        var update = false;
                        foreach (var edge in mcfg.GetEdges())
                        {
                            if (edge.Flow < edge.Capacity)
                            {
                                var ndist = dist[edge.From] + edge.Cost;
                                if (ndist < dist[edge.To])
                                {
                                    update        = true;
                                    dist[edge.To] = ndist;
                                }
                            }

                            if (edge.Flow == 0)
                            {
                                continue;
                            }
                            {
                                var ndist = dist[edge.To] - edge.Cost;
                                if (ndist < dist[edge.From])
                                {
                                    update          = true;
                                    dist[edge.From] = ndist;
                                }
                            }
                        }

                        if (!update)
                        {
                            break;
                        }
                    }
                });
            }
        }
        public void GetResidualGraph_must_work()
        {
            // Quelle und Senke erstellen.
            Vertex <string> source = new Vertex <string>("s");
            Vertex <string> target = new Vertex <string>("t");

            // alle weiteren Knoten des Graphens erstellen.
            Vertex <string> vA = new Vertex <string>("a");
            Vertex <string> vB = new Vertex <string>("b");
            Vertex <string> vC = new Vertex <string>("c");
            Vertex <string> vD = new Vertex <string>("d");

            // Den Graphen erstellen.
            FlowGraph <string> flowGraph = new FlowGraph <string>(source, target, new List <Vertex <string> >()
            {
                source, vA, vB, vC, vD, target
            });

            // Die Kanten des Graphens erstellen.
            flowGraph.AddEdge("s", "a", capacity: 5, flow: 5);
            flowGraph.AddEdge("s", "b", capacity: 7, flow: 3);
            flowGraph.AddEdge("a", "b", capacity: 7, flow: 3);
            flowGraph.AddEdge("a", "c", capacity: 4, flow: 2);
            flowGraph.AddEdge("b", "c", capacity: 3, flow: 3);
            flowGraph.AddEdge("b", "d", capacity: 3, flow: 3);
            flowGraph.AddEdge("c", "d", capacity: 4, flow: 0);
            flowGraph.AddEdge("c", "t", capacity: 5, flow: 5);
            flowGraph.AddEdge("d", "t", capacity: 6, flow: 3);

            FlowGraph <string> residualGraph = flowGraph.GetResidualGraph();

            // Die Kanten überprüfen
            Assert.AreEqual(13, residualGraph.Edges.Count);

            // a --> s
            Assert.AreEqual(vA, residualGraph.Edges[0].From);
            Assert.AreEqual(source, residualGraph.Edges[0].To);
            Assert.AreEqual(5, residualGraph.Edges[0].Capacity);
            Assert.AreEqual(-5, residualGraph.Edges[0].Flow);

            // s --> b
            Assert.AreEqual(source, residualGraph.Edges[1].From);
            Assert.AreEqual(vB, residualGraph.Edges[1].To);
            Assert.AreEqual(7, residualGraph.Edges[1].Capacity);
            Assert.AreEqual(4, residualGraph.Edges[1].Flow);

            // b --> s
            Assert.AreEqual(vB, residualGraph.Edges[2].From);
            Assert.AreEqual(source, residualGraph.Edges[2].To);
            Assert.AreEqual(7, residualGraph.Edges[2].Capacity);
            Assert.AreEqual(-3, residualGraph.Edges[2].Flow);

            // a --> b
            Assert.AreEqual(vA, residualGraph.Edges[3].From);
            Assert.AreEqual(vB, residualGraph.Edges[3].To);
            Assert.AreEqual(7, residualGraph.Edges[3].Capacity);
            Assert.AreEqual(4, residualGraph.Edges[3].Flow);

            // b --> a
            Assert.AreEqual(vB, residualGraph.Edges[4].From);
            Assert.AreEqual(vA, residualGraph.Edges[4].To);
            Assert.AreEqual(7, residualGraph.Edges[4].Capacity);
            Assert.AreEqual(-3, residualGraph.Edges[4].Flow);

            // a --> c
            Assert.AreEqual(vA, residualGraph.Edges[5].From);
            Assert.AreEqual(vC, residualGraph.Edges[5].To);
            Assert.AreEqual(4, residualGraph.Edges[5].Capacity);
            Assert.AreEqual(2, residualGraph.Edges[5].Flow);

            // c --> a
            Assert.AreEqual(vC, residualGraph.Edges[6].From);
            Assert.AreEqual(vA, residualGraph.Edges[6].To);
            Assert.AreEqual(4, residualGraph.Edges[6].Capacity);
            Assert.AreEqual(-2, residualGraph.Edges[6].Flow);

            // c --> b
            Assert.AreEqual(vC, residualGraph.Edges[7].From);
            Assert.AreEqual(vB, residualGraph.Edges[7].To);
            Assert.AreEqual(3, residualGraph.Edges[7].Capacity);
            Assert.AreEqual(-3, residualGraph.Edges[7].Flow);

            // d --> b
            Assert.AreEqual(vD, residualGraph.Edges[8].From);
            Assert.AreEqual(vB, residualGraph.Edges[8].To);
            Assert.AreEqual(3, residualGraph.Edges[8].Capacity);
            Assert.AreEqual(-3, residualGraph.Edges[8].Flow);

            // c --> d
            Assert.AreEqual(vC, residualGraph.Edges[9].From);
            Assert.AreEqual(vD, residualGraph.Edges[9].To);
            Assert.AreEqual(4, residualGraph.Edges[9].Capacity);
            Assert.AreEqual(4, residualGraph.Edges[9].Flow);

            // t --> c
            Assert.AreEqual(target, residualGraph.Edges[10].From);
            Assert.AreEqual(vC, residualGraph.Edges[10].To);
            Assert.AreEqual(5, residualGraph.Edges[10].Capacity);
            Assert.AreEqual(-5, residualGraph.Edges[10].Flow);

            // d --> t
            Assert.AreEqual(vD, residualGraph.Edges[11].From);
            Assert.AreEqual(target, residualGraph.Edges[11].To);
            Assert.AreEqual(6, residualGraph.Edges[11].Capacity);
            Assert.AreEqual(3, residualGraph.Edges[11].Flow);

            // t --> d
            Assert.AreEqual(target, residualGraph.Edges[12].From);
            Assert.AreEqual(vD, residualGraph.Edges[12].To);
            Assert.AreEqual(6, residualGraph.Edges[12].Capacity);
            Assert.AreEqual(-3, residualGraph.Edges[12].Flow);
        }
Beispiel #23
0
        public static void Solve()
        {
            var NM = Console.ReadLine().Split(" ").Select(int.Parse).ToArray();

            var(N, M) = (NM[0], NM[1]);
            var G  = new char[N][].Select(x => Console.ReadLine().ToCharArray()).ToArray();
            var fg = new FlowGraph(N * M + 2);
            var s  = N * M;
            var t  = N * M + 1;

            for (var i = 0; i < N; i++)
            {
                for (var j = 0; j < M; j++)
                {
                    if (G[i][j] == '#')
                    {
                        continue;
                    }
                    var v = i * M + j;
                    if ((i + j) % 2 == 0)
                    {
                        fg.AddEdge(s, v, 1);
                    }
                    else
                    {
                        fg.AddEdge(v, t, 1);
                    }
                }
            }

            var di = new[] { -1, 0, 1, 0 };
            var dj = new[] { 0, -1, 0, 1 };

            for (var i = 0; i < N; i++)
            {
                for (var j = 0; j < M; j++)
                {
                    if ((i + j) % 2 == 1 || G[i][j] == '#')
                    {
                        continue;
                    }
                    var v0 = i * M + j;
                    for (var k = 0; k < 4; k++)
                    {
                        var ci = i + di[k];
                        var cj = j + dj[k];
                        if (ci < 0 || N <= ci)
                        {
                            continue;
                        }
                        if (cj < 0 || M <= cj)
                        {
                            continue;
                        }
                        if (G[ci][cj] != '.')
                        {
                            continue;
                        }
                        var v1 = ci * M + cj;
                        fg.AddEdge(v0, v1, 1);
                    }
                }
            }

            Console.WriteLine(fg.MaxFlow(s, t));

            foreach (var edge in fg.GetEdges().Where(x => x.From != s && x.To != t && x.Flow != 0))
            {
                var(i0, j0) = (edge.From / M, edge.From % M);
                var(i1, j1) = (edge.To / M, edge.To % M);

                if (i0 == i1 + 1)
                {
                    G[i1][j1] = 'v';
                    G[i0][j0] = '^';
                }
                else if (j0 == j1 + 1)
                {
                    G[i1][j1] = '>';
                    G[i0][j0] = '<';
                }
                else if (i0 == i1 - 1)
                {
                    G[i0][j0] = 'v';
                    G[i1][j1] = '^';
                }
                else
                {
                    G[i0][j0] = '>';
                    G[i1][j1] = '<';
                }
            }

            Console.WriteLine(string.Join("\n", G.Select(x => new string(x))));
        }