Ejemplo n.º 1
0
        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);
                }
            }
        }
Ejemplo n.º 2
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))));
        }
Ejemplo n.º 3
0
        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;
                        }
                    }
                });
            }
        }
Ejemplo n.º 4
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))));
        }