コード例 #1
0
        public static long getMaxFlow(this MyGraph myGraph)
        {
            long totalFlow;
            var  pipes = myGraph.Pipes;
            var  nodes = myGraph.Nodes;

            int numNodes = nodes.Count();
            int numPipes = pipes.Count();

            char startingPoint = Char.Parse(myGraph.getStartingPoint());
            char endPoint      = Char.Parse(myGraph.getEndPoint());

            List <int> tails, heads, capacities;

            tails      = new List <int>();
            heads      = new List <int>();
            capacities = new List <int>();

            foreach (var node in nodes)
            {
                foreach (var pipe in node.Pipes)
                {
                    if (pipe.StartingValue > 0)
                    {
                        tails.Add(Char.Parse(pipe.StartingPoint) - 'A');
                        heads.Add(Char.Parse(pipe.EndPoint) - 'A');
                        capacities.Add(pipe.StartingValue);
                    }
                }
            }

            MaxFlow maxFlow = new MaxFlow();

            for (int i = 0; i < tails.Count(); ++i)
            {
                int arc = maxFlow.AddArcWithCapacity(tails[i], heads[i], capacities[i]);
                if (arc != i)
                {
                    throw new Exception("Internal error");
                }
            }
            int source = startingPoint - 'A';
            int sink   = endPoint - 'A';

            Console.WriteLine("Solving max flow with " + numNodes + " nodes, and " +
                              numPipes + " arcs, source=" + source + ", sink=" + sink);
            MaxFlow.Status solveStatus = maxFlow.Solve(source, sink);
            if (solveStatus == MaxFlow.Status.OPTIMAL)
            {
                totalFlow = maxFlow.OptimalFlow();
            }
            else
            {
                Console.WriteLine("Solving the max flow problem failed. Solver status: " +
                                  solveStatus);
                totalFlow = 0;
            }

            return(totalFlow);
        }
コード例 #2
0
ファイル: 3365322.cs プロジェクト: qifanyyy/CLCDSA
        public void Solve()
        {
            var n    = ri;
            var a    = Enumerate(n, x => rl);
            var mf   = new MaxFlow(2 * n + 2);
            var src  = 2 * n;
            var sink = src + 1;
            var ans  = 0L;

            for (int i = 1; i <= n; i++)
            {
                var v = a[i - 1];
                if (v < 0)
                {
                    //???????
                    mf.AddDirectedEdge(n + i - 1, sink, -v);
                }
                else
                {
                    ans += v;
                    //?????
                    mf.AddDirectedEdge(src, i - 1, v);
                }
                mf.AddDirectedEdge(i - 1, i + n - 1, INF);
                for (int j = 2 * i; j <= n; j += i)
                {
                    // j ??????i ?????????
                    mf.AddDirectedEdge(j - 1, i - 1 + n, INF);
                }
            }
            var val = mf.Execute(src, sink);

            Debug.WriteLine(val);
            Console.WriteLine(ans - val);
        }
コード例 #3
0
 public static void GetFlow(List <Nodes> node, int[,] matrix, int rootNode)
 {
     foreach (Nodes thisNode in node)
     {
         thisNode.flow = MaxFlow.fordFulkerson(matrix, rootNode, thisNode.index, matrix.GetLength(0));
     }
 }
コード例 #4
0
    public static void Main(string[] args)
    {
        Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
        int CASES = int.Parse(Console.ReadLine());

        for (int CASE = 1; CASE <= CASES; CASE++)
        {
            Console.Error.WriteLine("Case " + CASE);

            int        n  = int.Parse(Console.ReadLine());
            string[][] ws = new string[n][];
            for (int i = 0; i < n; i++)
            {
                ws[i] = Console.ReadLine().Split();
            }

            Dictionary <string, int> count1 = new Dictionary <string, int>();
            Dictionary <string, int> count2 = new Dictionary <string, int>();
            for (int i = 0; i < n; i++)
            {
                if (count1.ContainsKey(ws[i][0]))
                {
                    count1[ws[i][0]]++;
                }
                else
                {
                    count1[ws[i][0]] = 1;
                }
                if (count2.ContainsKey(ws[i][1]))
                {
                    count2[ws[i][1]]++;
                }
                else
                {
                    count2[ws[i][1]] = 1;
                }
            }

            string[] firsts  = count1.Keys.ToArray();
            string[] seconds = count2.Keys.ToArray();

            MaxFlow mf = new MaxFlow(n * 2);
            for (int i = 0; i < firsts.Length; i++)
            {
                mf.Add(mf.Source, i, count1[firsts[i]] - 1);
            }

            for (int i = 0; i < seconds.Length; i++)
            {
                mf.Add(n + i, mf.Sink, count2[seconds[i]] - 1);
            }

            for (int i = 0; i < n; i++)
            {
                mf.Add(Array.IndexOf(firsts, ws[i][0]), n + Array.IndexOf(seconds, ws[i][1]), 1);
            }

            Console.WriteLine("Case #" + CASE + ": " + mf.NetworkFlow());
        }
    }
コード例 #5
0
            public void Solve()
            {
                int N     = NextInt();
                var Alist = new List <ti3>();
                var Blist = new List <ti3>();

                var s = 0;
                var t = 2 * N + 1;

                var mf = new MaxFlow(t + 1);

                N.REP(i =>
                {
                    var ai = NextInt();
                    var bi = NextInt();

                    Alist.Add(new ti3(ai, bi, i + 1));
                    mf.Add(s, i + 1, 1);
                });

                N.REP(i =>
                {
                    var ai = NextInt();
                    var bi = NextInt();

                    Alist.Add(new ti3(ai, bi, i + N + 1));
                    mf.Add(i + N + 1, t, 1);
                });

                var list = Alist.Concat(Blist).OrderBy(x => x.Item1).Select(item => new ti2(item.Item2, item.Item3)).ToList();

                for (int i = 0; i < list.Count; i++)
                {
                    var a = list[i].Item2;
                    if (a > N)
                    {
                        continue;
                    }
                    var ay = list[i].Item1;
                    for (int j = i + 1; j < list.Count; j++)
                    {
                        var b = list[j].Item2;
                        if (b < N + 1)
                        {
                            continue;
                        }
                        var by = list[j].Item1;
                        if (by < ay)
                        {
                            continue;
                        }

                        mf.Add(a, b, 1);
                    }
                }

                mf.Run(s, t).WL();

                return;
            }
コード例 #6
0
        public void EdmondsKarpTest()
        {
            var data        = CreateMaxFlowData();
            var maxFlowTool = new MaxFlow <string>();
            var maxFlow     = maxFlowTool.EdmondsKarp(data.Item1, data.Item2, data.Item3);

            Assert.AreEqual(5, maxFlow);
        }
コード例 #7
0
    static void Main()
    {
        // [START data]
        // Define three parallel arrays: start_nodes, end_nodes, and the capacities
        // between each pair. For instance, the arc from node 0 to node 1 has a
        // capacity of 20.
        // From Taha's 'Introduction to Operations Research',
        // example 6.4-2.
        int[] startNodes = { 0, 0, 0, 1, 1, 2, 2, 3, 3 };
        int[] endNodes   = { 1, 2, 3, 2, 4, 3, 4, 2, 4 };
        int[] capacities = { 20, 30, 10, 40, 30, 10, 20, 5, 20 };
        // [END data]

        // [START constraints]
        // Instantiate a SimpleMaxFlow solver.
        MaxFlow maxFlow = new MaxFlow();

        // Add each arc.
        for (int i = 0; i < startNodes.Length; ++i)
        {
            int arc = maxFlow.AddArcWithCapacity(startNodes[i], endNodes[i],
                                                 capacities[i]);
            if (arc != i)
            {
                throw new Exception("Internal error");
            }
        }
        // [END constraints]

        // [START solve]
        // Find the maximum flow between node 0 and node 4.
        int solveStatus = maxFlow.Solve(0, 4);

        // [END solve]

        // [START print_solution]
        if (solveStatus == MaxFlow.OPTIMAL)
        {
            Console.WriteLine("Max. flow: " + maxFlow.OptimalFlow());
            Console.WriteLine("");
            Console.WriteLine("  Arc     Flow / Capacity");
            for (int i = 0; i < maxFlow.NumArcs(); ++i)
            {
                Console.WriteLine(maxFlow.Tail(i) + " -> " +
                                  maxFlow.Head(i) + "    " +
                                  string.Format("{0,3}", maxFlow.Flow(i)) + "  /  " +
                                  string.Format("{0,3}", maxFlow.Capacity(i)));
            }
        }
        else
        {
            Console.WriteLine("Solving the max flow problem failed. Solver status: " +
                              solveStatus);
        }
        // [END print_solution]
    }
コード例 #8
0
ファイル: A.cs プロジェクト: sakapon/AtCoder-Contests
    static void Main()
    {
        var h = Read();
        int nx = h[0], ny = h[1];
        var es = Array.ConvertAll(new bool[h[2]], _ => Read());

        var r = MaxFlow.BipartiteMatching(nx, ny, es);

        Console.WriteLine(r.Length);
    }
コード例 #9
0
    /// <summary>
    /// Evaluates the similarity between two maps using the graph sampling evaluation of biagioni and eriksson.
    /// Parameters are hardcoded, based on the ones we used in the corresponding research.
    /// </summary>
    /// <param name="GT">The ground truth map</param>
    /// <param name="CT">the constructed map.</param>
    /// <param name="amount">the amount of neighbourhood evaluations we average over</param>
    /// <returns>A precision and recall value indicating the similarity between the maps.</returns>
    public (float, float) EvalMap(Map GT, Map CT, int amount)
    {
        float precision = 0;
        float recall    = 0;

        for (int k = 0; k < amount; k++)
        {
            Coordinate originGT = rand.GetRandomPointOnRoad(rand.GetWeightedRandomRoad(GT));
            Coordinate originCT = CT.GetClosestPoint(originGT.location);

            /* An extra step that is sometimes used in the literature when ground truth map is not pruned.
             * while (Vector3.Distance(originCT.location, originGT.location) > 50)
             * {
             *  originGT = rand.GetRandomCoordinate(rand.GetWeightedRandomRoad(GT));
             *  originCT = CT.GetClosestPoint(originGT.location);
             * }
             */

            List <Vector3> pointsGT = sampleNeighbourhood.GetNeighbourhood(GT, originGT, 500, 30);
            List <Vector3> pointsCT = sampleNeighbourhood.GetNeighbourhood(CT, originCT, 500, 30);

            MaxFlow flow = new MaxFlow(pointsGT.Count + pointsCT.Count + 2);

            for (int i = 0; i < pointsCT.Count; i++)
            {
                flow.AddEdge(0, i + 1, 1);
            }

            for (int i = 0; i < pointsCT.Count; i++)
            {
                Vector3 pointCT = pointsCT[i];

                for (int j = 0; j < pointsGT.Count; j++)
                {
                    Vector3 pointGT = pointsGT[j];
                    if (Vector3.Distance(pointCT, pointGT) < 20)
                    {
                        flow.AddEdge(i + 1, j + pointsCT.Count + 1, 1);
                    }
                }
            }

            for (int i = 0; i < pointsGT.Count; i++)
            {
                flow.AddEdge(i + pointsCT.Count + 1, 1 + pointsCT.Count + pointsGT.Count, 1);
            }

            float matching = flow.FindMaximumFlow(0, 1 + pointsCT.Count + pointsGT.Count).Item1;
            precision += pointsCT.Count > 0 ? matching / pointsCT.Count : 0;
            recall    += pointsGT.Count > 0 ? matching / pointsGT.Count : 0;
        }

        return(precision / amount, recall / amount);
    }
コード例 #10
0
ファイル: A.cs プロジェクト: sakapon/AtCoder-Contests
    static void Main()
    {
        var h  = Read();
        var n  = h[0];
        var es = Array.ConvertAll(new bool[h[1]], _ => Read());

        var mf = new MaxFlow(n);

        mf.AddEdges(es);
        Console.WriteLine(mf.Dinic(0, n - 1));
    }
コード例 #11
0
    void Calc()
    {
        int N = re.i();

        int[] A = new int[N];
        int[] B = new int[N];
        int[] C = new int[N];
        int[] D = new int[N];
        for (int i = 0; i < N; i++)
        {
            A[i] = re.i();
            B[i] = re.i();
        }
        for (int i = 0; i < N; i++)
        {
            C[i] = re.i();
            D[i] = re.i();
        }
        List <int>  f    = new List <int>();
        List <int>  t    = new List <int>();
        List <long> capa = new List <long>();
        int         S    = 2 * N;
        int         G    = 2 * N + 1;

        for (int i = 0; i < N; i++)
        {
            f.Add(S);
            t.Add(i);
            capa.Add(1);
        }
        for (int i = 0; i < N; i++)
        {
            f.Add(i + N);
            t.Add(G);
            capa.Add(1);
        }
        for (int i = 0; i < N; i++)
        {
            for (int j = 0; j < N; j++)
            {
                if (A[i] < C[j] && B[i] < D[j])
                {
                    f.Add(i);
                    t.Add(j + N);
                    capa.Add(1);
                }
            }
        }
        MaxFlow F     = new MaxFlow(f.ToArray(), t.ToArray(), capa.ToArray(), 2 * N + 2, S, G);
        long    count = F.flow;

        sb.Append(count + "\n");
    }
コード例 #12
0
    // Driver code
    public static void Main()
    {
        // Let us create a graph shown in the above example
        int[,] graph = new int[, ] {
            { 0, 16, 13, 0, 0, 0 }, { 0, 0, 10, 12, 0, 0 },
            { 0, 4, 0, 0, 14, 0 }, { 0, 0, 9, 0, 0, 20 },
            { 0, 0, 0, 7, 0, 4 }, { 0, 0, 0, 0, 0, 0 }
        };
        MaxFlow m = new MaxFlow();

        Console.WriteLine("The maximum possible flow is "
                          + m.fordFulkerson(graph, 0, 5));
    }
コード例 #13
0
    /// <summary>
    /// Visualizes and evaluates a single random neighbourhood.
    /// </summary>
    /// <param name="GT">Ground truth map</param>
    /// <param name="CT">contructed map</param>
    /// <param name="originDistanceCondition"></param>
    /// <param name="matchDistance"></param>
    /// <returns></returns>
    public (float, float) EvalNeighbourhood(Map GT, Map CT)
    {
        Coordinate originGT = rand.GetRandomPointOnRoad(rand.GetWeightedRandomRoad(GT));
        Coordinate originCT = CT.GetClosestPoint(originGT.location);

        /* An extra step that is sometimes used in the literature when ground truth map is not pruned.
         * while (Vector3.Distance(originCT.location, originGT.location) > 50)
         * {
         *  originGT = rand.GetRandomCoordinate(rand.GetWeightedRandomRoad(GT));
         *  originCT = CT.GetClosestPoint(originGT.location);
         * }
         */

        List <Vector3> pointsGT = sampleNeighbourhood.GetNeighbourhood(GT, originGT, 150, 30);
        List <Vector3> pointsCT = sampleNeighbourhood.GetNeighbourhood(CT, originCT, 150, 30);

        MaxFlow flow = new MaxFlow(pointsGT.Count + pointsCT.Count + 2);

        for (int i = 0; i < pointsCT.Count; i++)
        {
            flow.AddEdge(0, i + 1, 1);           // source edges
        }
        for (int i = 0; i < pointsCT.Count; i++) // edges between CT and GT
        {
            Vector3 pointCT = pointsCT[i];

            for (int j = 0; j < pointsGT.Count; j++)
            {
                Vector3 pointGT = pointsGT[j];
                if (Vector3.Distance(pointCT, pointGT) < 20)
                {
                    flow.AddEdge(i + 1, j + pointsCT.Count + 1, 1);
                }
            }
        }

        for (int i = 0; i < pointsGT.Count; i++)
        {
            flow.AddEdge(i + pointsCT.Count + 1, 1 + pointsCT.Count + pointsGT.Count, 1);                                      // sink edges
        }
        float matching;

        int[,] graph;
        (matching, graph) = flow.FindMaximumFlow(0, 1 + pointsCT.Count + pointsGT.Count);

        float prec   = pointsCT.Count > 0 ? matching / pointsCT.Count : 0;
        float recall = pointsGT.Count > 0 ? matching / pointsGT.Count : 0;

        return(prec, recall);
    }
コード例 #14
0
ファイル: csflow.cs プロジェクト: zirui-zhang/or-tools
    private static void SolveMaxFlow()
    {
        Console.WriteLine("Max Flow Problem");
        int numNodes = 6;
        int numArcs  = 9;

        int[]   tails             = { 0, 0, 0, 0, 1, 2, 3, 3, 4 };
        int[]   heads             = { 1, 2, 3, 4, 3, 4, 4, 5, 5 };
        int[]   capacities        = { 5, 8, 5, 3, 4, 5, 6, 6, 4 };
        int[]   expectedFlows     = { 4, 4, 2, 0, 4, 4, 0, 6, 4 };
        int     expectedTotalFlow = 10;
        MaxFlow maxFlow           = new MaxFlow();

        for (int i = 0; i < numArcs; ++i)
        {
            int arc = maxFlow.AddArcWithCapacity(tails[i], heads[i], capacities[i]);
            if (arc != i)
            {
                throw new Exception("Internal error");
            }
        }
        int source = 0;
        int sink   = numNodes - 1;

        Console.WriteLine("Solving max flow with " + numNodes + " nodes, and " +
                          numArcs + " arcs, source=" + source + ", sink=" + sink);
        int solveStatus = maxFlow.Solve(source, sink);

        if (solveStatus == MaxFlow.OPTIMAL)
        {
            long totalFlow = maxFlow.OptimalFlow();
            Console.WriteLine("total computed flow " + totalFlow +
                              ", expected = " + expectedTotalFlow);
            for (int i = 0; i < numArcs; ++i)
            {
                Console.WriteLine("Arc " + i + " (" + maxFlow.Tail(i) + " -> " +
                                  maxFlow.Head(i) + "), capacity = " +
                                  maxFlow.Capacity(i) + ") computed = " +
                                  maxFlow.Flow(i) + ", expected = " + expectedFlows[i]);
            }
        }
        else
        {
            Console.WriteLine("Solving the max flow problem failed. Solver status: " +
                              solveStatus);
        }
    }
コード例 #15
0
    public static void Main()
    {
        int[,] graph = { { 0, 5, 4, 0, 0, 0 },
                         { 0, 0, 3, 5, 3, 0 },
                         { 0, 0, 0, 8, 2, 0 },
                         { 0, 0, 0, 0, 6, 4 },
                         { 0, 0, 0, 0, 0, 5 },
                         { 0, 0, 0, 0, 0, 0 } };

        var m = new MaxFlow();

        Console.OutputEncoding = Encoding.UTF8;
        Console.WriteLine("Максимальний потік " +
                          m.FordFulkerson(graph, 0, 5));

        Console.ReadKey();
    }
コード例 #16
0
ファイル: 1766459.cs プロジェクト: qifanyyy/CLCDSA
    void Calc()
    {
        int N = re.i();

        N++;
        long[] A     = new long[N];
        long   count = 0;

        for (int i = 1; i < N; i++)
        {
            A[i]   = re.i();
            count += Math.Max(A[i], 0);
        }
        List <int>  f    = new List <int>();
        List <int>  t    = new List <int>();
        List <long> cost = new List <long>();

        for (int i = 0; i < N; i++)
        {
            if (A[i] > 0)
            {
                f.Add(N);
                t.Add(i);
                cost.Add(A[i]);
            }
            else
            {
                f.Add(i);
                t.Add(N + 1);
                cost.Add(-A[i]);
            }
        }
        for (int i = 1; i < N; i++)
        {
            for (int j = i * 2; j < N; j += i)
            {
                f.Add(j);
                t.Add(i);
                cost.Add(1000000000000);
            }
        }
        MaxFlow MF = new MaxFlow(f.ToArray(), t.ToArray(), cost.ToArray(), N + 2, N, N + 1);

        count -= MF.flow;
        sb.Append(count + "\n");
    }
コード例 #17
0
ファイル: A.cs プロジェクト: sakapon/AtCoder-Contests
    // このコードはテンプレートとして使えます。
    // 0 <= v1 < n1, 0 <= v2 < n2
    public static int[][] BipartiteMatching(int n1, int n2, int[][] des)
    {
        var sv = n1 + n2;
        var ev = sv + 1;
        var mf = new MaxFlow(ev + 1);

        for (int i = 0; i < n1; ++i)
        {
            mf.AddEdge(sv, i, 1);
        }
        for (int j = 0; j < n2; ++j)
        {
            mf.AddEdge(n1 + j, ev, 1);
        }
        foreach (var e in des)
        {
            mf.AddEdge(e[0], n1 + e[1], 1);
        }

        mf.Dinic(sv, ev);
        var map = mf.Map;

        var r = new List <int[]>();

        foreach (var se in map[sv])
        {
            if (se.Capacity > 0)
            {
                continue;
            }

            foreach (var e in map[se.To])
            {
                if (e.Capacity == 0)
                {
                    r.Add(new[] { se.To, e.To - n1 });
                    break;
                }
            }
        }
        return(r.ToArray());
    }
コード例 #18
0
ファイル: csflow.cs プロジェクト: RickOne16/or-tools
 private static void SolveMaxFlow()
 {
   Console.WriteLine("Max Flow Problem");
   int numNodes = 6;
   int numArcs = 9;
   int[] tails = {0, 0, 0, 0, 1, 2, 3, 3, 4};
   int[] heads = {1, 2, 3, 4, 3, 4, 4, 5, 5};
   int[] capacities = {5, 8, 5, 3, 4, 5, 6, 6, 4};
   int[] expectedFlows = {4, 4, 2, 0, 4, 4, 0, 6, 4};
   int expectedTotalFlow = 10;
   MaxFlow maxFlow = new MaxFlow();
   for (int i = 0; i < numArcs; ++i)
   {
     int arc = maxFlow.AddArcWithCapacity(tails[i], heads[i], capacities[i]);
     if (arc != i) throw new Exception("Internal error");
   }
   int source = 0;
   int sink = numNodes - 1;
   Console.WriteLine("Solving max flow with " + numNodes + " nodes, and " +
                     numArcs + " arcs, source=" + source + ", sink=" + sink);
   int solveStatus = maxFlow.Solve(source, sink);
   if (solveStatus == MaxFlow.OPTIMAL)
   {
     long totalFlow = maxFlow.OptimalFlow();
     Console.WriteLine("total computed flow " + totalFlow +
                       ", expected = " + expectedTotalFlow);
     for (int i = 0; i < numArcs; ++i)
     {
       Console.WriteLine("Arc " + i + " (" + maxFlow.Head(i) + " -> " +
                         maxFlow.Tail(i) + "), capacity = " +
                         maxFlow.Capacity(i) + ") computed = " +
                         maxFlow.Flow(i) + ", expected = " + expectedFlows[i]);
     }
   }
   else
   {
     Console.WriteLine("Solving the max flow problem failed. Solver status: " +
                       solveStatus);
   }
 }
コード例 #19
0
ファイル: 2254885.cs プロジェクト: qifanyyy/CLCDSA
            public void Solve()
            {
                int N  = NextInt();
                var s  = 0;
                var t  = 2 * N + 1;
                var mf = new MaxFlow(t + 1);

                var A = new List <ti2>();
                var B = new List <ti2>();

                N.REP(i => {
                    A.Add(NextInt(), NextInt());
                    mf.Add(s, i + 1, 1);
                });
                N.REP(i => {
                    B.Add(NextInt(), NextInt());
                    mf.Add(i + N + 1, t, 1);
                });

                for (int i = 0; i < N; i++)
                {
                    var ax = A[i].Item1;
                    var ay = A[i].Item2;

                    for (int j = 0; j < N; j++)
                    {
                        var bx = B[j].Item1;
                        var by = B[j].Item2;

                        if (ax < bx && ay < by)
                        {
                            mf.Add(i + 1, j + N + 1, 1);
                        }
                    }
                }

                mf.Run(s, t).WL();

                return;
            }
コード例 #20
0
    public static int Solve(HashSet <string>[] sent)
    {
        int N = sent.Length;
        Dictionary <string, int> words = new Dictionary <string, int>();

        int[][] ws = new int[N][];
        for (int i = 0; i < N; i++)
        {
            ws[i] = new int[sent[i].Count];
            int j = 0;
            foreach (string w in sent[i])
            {
                if (!words.ContainsKey(w))
                {
                    words[w] = words.Count;
                }
                ws[i][j++] = words[w];
            }
        }

        MaxFlow mf = new MaxFlow(N + words.Count * 2);

        for (int i = 0; i < words.Count; i++)
        {
            mf.Add(N + i, N + words.Count + i, 1);
        }

        for (int i = 0; i < N; i++)
        {
            for (int j = 0; j < ws[i].Length; j++)
            {
                mf.Add(i, N + ws[i][j], 1);
                mf.Add(N + words.Count + ws[i][j], i, 1);
            }
        }

        return(mf.NetworkFlow(0, 1));
    }
コード例 #21
0
ファイル: csflow.cs プロジェクト: mikesurface/or-tools
    private static void SolveMaxFlow()
    {
        Console.WriteLine("Max Flow Problem");
        int numNodes = 6;
        int numArcs  = 9;

        int[]     tails             = { 0, 0, 0, 0, 1, 2, 3, 3, 4 };
        int[]     heads             = { 1, 2, 3, 4, 3, 4, 4, 5, 5 };
        int[]     capacities        = { 5, 8, 5, 3, 4, 5, 6, 6, 4 };
        int[]     expectedFlows     = { 4, 4, 2, 0, 4, 4, 0, 6, 4 };
        int       expectedTotalFlow = 10;
        StarGraph graph             = new StarGraph(numNodes, numArcs);
        MaxFlow   maxFlow           = new MaxFlow(graph, 0, numNodes - 1);

        for (int i = 0; i < numArcs; ++i)
        {
            int arc = graph.AddArc(tails[i], heads[i]);
            maxFlow.SetArcCapacity(arc, capacities[i]);
        }
        Console.WriteLine("Solving max flow with " + numNodes + " nodes, and " +
                          numArcs + " arcs, source = 0, sink = " + (numNodes - 1));
        if (maxFlow.Solve())
        {
            long totalFlow = maxFlow.GetOptimalFlow();
            Console.WriteLine("total computed flow " + totalFlow +
                              ", expected = " + expectedTotalFlow);
            for (int i = 0; i < numArcs; ++i)
            {
                Console.WriteLine("Arc " + i + " (" + heads[i] + " -> " + tails[i] +
                                  ", capacity = " + capacities[i] + ") computed = " +
                                  maxFlow.Flow(i) + ", expected = " + expectedFlows[i]);
            }
        }
        else
        {
            Console.WriteLine("No solution found");
        }
    }
コード例 #22
0
        public void Solve()
        {
            var n = sc.Integer();
            var g = sc.Integer();
            var E = sc.Integer();
            var p = sc.Integer(g);
            var G = new MaxFlow(n + 1);

            for (int i = 0; i < E; i++)
            {
                var a = sc.Integer();
                var b = sc.Integer();
                G.AddUndirectedEdge(a, b, 1);
            }
            foreach (var q in p)
            {
                G.AddDirectedEdge(q, n, 1);
            }

            var cost = G.GetMaxFlow(0, n);

            IO.Printer.Out.WriteLine(cost);
        }
コード例 #23
0
ファイル: F.cs プロジェクト: sakapon/AtCoder-Contests
    static object Solve()
    {
        var(h, w, n) = Read3();
        var ps = Array.ConvertAll(new bool[n], _ => Read4());

        var sv = 400;
        var ev = sv + 1;
        var mf = new MaxFlow(ev + 1);

        for (int i = 0; i < h; i++)
        {
            mf.AddEdge(sv, i, 1);
        }
        for (int i = 0; i < w; i++)
        {
            mf.AddEdge(300 + i, ev, 1);
        }

        for (int i = 0; i < n; i++)
        {
            var(a, b, c, d) = ps[i];
            var ri = 100 + i;
            var ci = 200 + i;
            mf.AddEdge(ri, ci, 1);

            for (int j = a - 1; j < c; j++)
            {
                mf.AddEdge(j, ri, 1);
            }
            for (int j = b - 1; j < d; j++)
            {
                mf.AddEdge(ci, 300 + j, 1);
            }
        }

        return(mf.Dinic(sv, ev));
    }
コード例 #24
0
ファイル: 8.cs プロジェクト: qifanyyy/CLCDSA
    private static void Go()
    {
        var n = RI();
        var m = RI();

        var x = new List <Item>();
        var p = new List <Item>();

        var extraX = new List <Item>();
        var extraP = new List <Item>();

        for (int i = 0; i < m; i++)
        {
            var newItem = new Item();
            newItem.Tp = ReadAnyOf(new char[] { 'x', '+', 'o' });
            newItem.X  = RI() - 1;
            newItem.Y  = RI() - 1;

            if (newItem.Tp == 'x' || newItem.Tp == 'o')
            {
                x.Add(newItem);
            }
            if (newItem.Tp == '+' || newItem.Tp == 'o')
            {
                p.Add(newItem);
            }
        }

        var xx = Enumerable.Range(0, n).Except(x.Select(xxx => xxx.X)).ToList();
        var yy = Enumerable.Range(0, n).Except(x.Select(xxx => xxx.Y)).ToList();

        for (int i = 0; i < xx.Count; i++)
        {
            extraX.Add(new Item()
            {
                X = xx[i], Y = yy[i], Tp = 'x'
            });
        }

        // 0 - root
        // 1 - N+N-1 > D1
        // N+N - N+N+N+N-1 > D
        // 4N > exist.

        var d1 = new bool[n + n - 1]; // x+y
        var d2 = new bool[n + n - 1]; // x-y+n-1

        foreach (var t in p)
        {
            d1[t.X + t.Y]         = true;
            d2[t.X - t.Y + n - 1] = true;
        }

        var nn = 4 * n + 1;

        var map = new int[nn, nn];

        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (!d1[i + j] && !d2[i - j + n - 1])
                {
                    var d1Id = i + j;
                    var d2Id = i - j + n - 1;

                    var v1 = 1 + d1Id;
                    var v2 = n + n + d2Id;

                    map[0, v1]      = 1;
                    map[v1, v2]     = 1;
                    map[v2, nn - 1] = 1;
                }
            }
        }

        var flow    = new MaxFlow(map, nn);
        var maxFlow = flow.GetMaxFlow(0, nn - 1);

        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (!d1[i + j] && !d2[i - j + n - 1])
                {
                    var d1Id = i + j;
                    var d2Id = i - j + n - 1;

                    var v1 = 1 + d1Id;
                    var v2 = n + n + d2Id;

                    if (map[v1, v2] == 0)
                    {
                        extraP.Add(new Item()
                        {
                            X = i, Y = j, Tp = '+'
                        });
                    }
                }
            }
        }

        var q1 = new char[n, n];

        foreach (var t in x)
        {
            q1[t.X, t.Y] = t.Tp;
        }
        foreach (var t in p)
        {
            q1[t.X, t.Y] = t.Tp;
        }

        var q2 = (char[, ])(q1.Clone());

        foreach (var t in extraX)
        {
            if (q2[t.X, t.Y] == '+')
            {
                t.Tp = 'o';
            }
            q2[t.X, t.Y] = t.Tp;
        }

        foreach (var t in extraP)
        {
            if (q2[t.X, t.Y] == 'x')
            {
                t.Tp = 'o';
            }
            q2[t.X, t.Y] = t.Tp;
        }

        var result = new List <Item>();

        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (q1[i, j] != q2[i, j])
                {
                    result.Add(new Item()
                    {
                        X = i, Y = j, Tp = q2[i, j]
                    });
                }
            }
        }

        var sb = new StringBuilder();

        var max = x.Count + p.Count + extraX.Count + extraP.Count;

        sb.Append(max + " " + result.Count);
        foreach (var t in result)
        {
            sb.AppendLine();
            sb.Append(t.ToString());
        }

        SetAnswer(sb.ToString());
    }
コード例 #25
0
ファイル: 1492436.cs プロジェクト: qifanyyy/CLCDSA
        public void Solve()
        {
            var       n   = ri;
            const int MAX = 10000005;
            var       a   = new int[MAX];
            var       b   = new int[MAX];

            foreach (var x in sc.Integer(n))
            {
                a[x] = 1;
            }
            for (int i = 0; i < MAX - 1; i++)
            {
                b[i] = a[i + 1] ^ a[i];
            }
            var xs = Enumerate(2, x => new List <int>());

            for (int i = 0; i < MAX; i++)
            {
                if (b[i] == 1)
                {
                    xs[i % 2].Add(i);
                }
            }


            var isprime = MathEx.Sieve(10000005);

            isprime[2] = false;

            var m = xs[0].Count + xs[1].Count;

            Debug.WriteLine(m);
            Debug.WriteLine(xs[0].AsJoinedString());
            Debug.WriteLine(xs[1].AsJoinedString());
            var G = new MaxFlow(m + 2);

            for (int i = 0; i < xs[0].Count; i++)
            {
                for (int j = 0; j < xs[1].Count; j++)
                {
                    if (isprime[Math.Abs(xs[0][i] - xs[1][j])])
                    {
                        G.AddDirectedEdge(i, xs[0].Count + j, 1);
                    }
                }
            }
            var f = m;
            var t = m + 1;

            for (int i = 0; i < xs[0].Count; i++)
            {
                G.AddDirectedEdge(f, i, 1);
            }
            for (int i = 0; i < xs[1].Count; i++)
            {
                G.AddDirectedEdge(xs[0].Count + i, t, 1);
            }
            var mf  = G.Execute(f, t);
            var ans = mf;
            var u   = xs[0].Count - mf;
            var v   = xs[1].Count - mf;

            ans += 2 * (u / 2);
            ans += 2 * (v / 2);
            if (u % 2 == 1)
            {
                ans += 3;
            }
            IO.Printer.Out.WriteLine(ans);
        }
コード例 #26
0
    static void Main()
    {
        var(n, m) = Read2();
        var s = Array.ConvertAll(new bool[n], _ => Console.ReadLine().ToCharArray());

        var sv = n * m;
        var ev = sv + 1;
        var mf = new MaxFlow(ev + 1);

        var vs0 = new List <int>();
        var vs1 = new HashSet <int>();

        // checker board
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                if (s[i][j] == '#')
                {
                    continue;
                }

                var v = m * i + j;
                if ((i + j) % 2 == 0)
                {
                    mf.AddEdge(sv, v, 1);
                    vs0.Add(v);
                }
                else
                {
                    mf.AddEdge(v, ev, 1);
                    vs1.Add(v);
                }
            }
        }

        foreach (var v in vs0)
        {
            if (vs1.Contains(v - m))
            {
                mf.AddEdge(v, v - m, 1);
            }
            if (vs1.Contains(v + m))
            {
                mf.AddEdge(v, v + m, 1);
            }
            if (v % m != 0 && vs1.Contains(v - 1))
            {
                mf.AddEdge(v, v - 1, 1);
            }
            if (v % m != m - 1 && vs1.Contains(v + 1))
            {
                mf.AddEdge(v, v + 1, 1);
            }
        }

        var M   = mf.Dinic(sv, ev);
        var map = mf.Map;

        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                if (s[i][j] == '#')
                {
                    continue;
                }

                var v = m * i + j;
                if ((i + j) % 2 == 0)
                {
                    var v2 = map[v].FirstOrDefault(e => e.Capacity == 0 && e.To != sv)?.To;
                    if (v2 == null)
                    {
                        continue;
                    }

                    var(i2, j2) = ((int)v2 / m, (int)v2 % m);
                    if (i == i2)
                    {
                        s[i][Math.Min(j, j2)] = '>';
                        s[i][Math.Max(j, j2)] = '<';
                    }
                    else
                    {
                        s[Math.Min(i, i2)][j] = 'v';
                        s[Math.Max(i, i2)][j] = '^';
                    }
                }
            }
        }

        Console.WriteLine(M);
        foreach (var r in s)
        {
            Console.WriteLine(new string(r));
        }
    }
コード例 #27
0
ファイル: 16.cs プロジェクト: qifanyyy/CLCDSA
    public static string Solve()
    {
        // Read input
        string[] ps = Console.ReadLine().Split();
        int      N  = int.Parse(ps[0]);
        int      R  = int.Parse(ps[1]);
        int      O  = int.Parse(ps[2]);
        int      Y  = int.Parse(ps[3]);
        int      G  = int.Parse(ps[4]);
        int      B  = int.Parse(ps[5]);
        int      V  = int.Parse(ps[6]);

        // Static stuff
        int[]  counts = new int[6];
        string chars  = "RYBGVO";

        counts[0]         = R;
        counts[1]         = Y;
        counts[2]         = B;
        counts[3]         = G;
        counts[4]         = V;
        counts[5]         = O;
        bool[,] conflicts = new bool[7, 7];
        for (int i = 0; i < 6; i++)
        {
            conflicts[i, i] = true;
        }
        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                if (i != j)
                {
                    conflicts[i, 3 + j] = conflicts[3 + j, i] = true;
                }
            }
        }

        // Do a matching to find a neighbour for everyone
        MaxFlow mf  = new MaxFlow(N * 2);
        int     idx = 0;

        int[] col = new int[N];
        for (int i = 0; i < 6; i++)
        {
            for (int j = 0; j < counts[i]; j++)
            {
                col[idx++] = i;
            }
        }
        for (int i = 0; i < N; i++)
        {
            mf.Add(mf.Source, i, 1);
            mf.Add(N + i, mf.Sink, 1);
            for (int j = 0; j < N; j++)
            {
                if (!conflicts[col[i], col[j]])
                {
                    mf.Add(i, N + j, 1);
                }
            }
        }
        if (mf.NetworkFlow() != N)
        {
            return(null);
        }
        int[] next = new int[N];
        for (int i = 0; i < N; i++)
        {
            while (mf.flow[i, N + next[i]] == 0)
            {
                next[i]++;
            }
        }

        // Construct cycles
        bool[]             done   = new bool[N];
        List <List <int> > cycles = new List <List <int> >();

        for (int i = 0; i < N; i++)
        {
            if (done[i])
            {
                continue;
            }
            List <int> cycle = new List <int>();
            cycle.Add(i);
            int cur = next[i];
            while (cur != i)
            {
                done[cur] = true;
                cycle.Add(cur);
                cur = next[cur];
            }
            cycles.Add(cycle);
        }

        while (cycles.Count > 1)
        {
            // merge two cycles
            bool found  = false;
            int  mergeC = -1;
            int  mergeI = -1;
            int  mergeK = -1;
            for (int i = 0; !found && i < cycles[0].Count; i++)
            {
                for (int j = 1; !found && j < cycles.Count; j++)
                {
                    for (int k = 0; !found && k < cycles[j].Count; k++)
                    {
                        if (col[cycles[0][i]] == col[cycles[j][k]])
                        {
                            found  = true;
                            mergeC = j;
                            mergeI = i;
                            mergeK = k;
                        }
                    }
                }
            }
            if (!found)
            {
                return(null);
            }
            List <int> comb = new List <int>();

            comb.AddRange(cycles[0].GetRange(0, mergeI));
            comb.AddRange(cycles[mergeC].GetRange(mergeK, cycles[mergeC].Count - mergeK));
            comb.AddRange(cycles[mergeC].GetRange(0, mergeK));
            comb.AddRange(cycles[0].GetRange(mergeI, cycles[0].Count - mergeI));

            cycles.RemoveAt(0);
            cycles.RemoveAt(0);
            cycles.Add(comb);
        }

        // Construct the anwer
        char[] res = new char[N];
        for (int i = 0; i < N; i++)
        {
            res[i] = chars[col[cycles[0][i]]];
        }
        return(new string(res));
    }
コード例 #28
0
    public static void Main(string[] args)
    {
        int cases = int.Parse(Console.ReadLine());

        while (cases-- > 0)
        {
            int      N    = int.Parse(Console.ReadLine());
            string[] grid = new string[N];
            for (int i = 0; i < N; i++)
            {
                grid[i] = Console.ReadLine();
            }
            int notPlayed = 0;
            int[,] ind = new int[N, N];
            for (int i = 0; i < N; i++)
            {
                for (int j = i + 1; j < N; j++)
                {
                    if (grid[i][j] == '.')
                    {
                        ind[i, j] = N + notPlayed++;
                    }
                }
            }
            MaxFlow mf     = new MaxFlow(notPlayed + N);
            int[]   pts    = new int[N];
            int[]   optpts = new int[N];
            int     totalP = 0;
            for (int i = 0; i < N; i++)
            {
                mf.Add(i, mf.Sink, 2 * N);
                for (int j = 0; j < N; j++)
                {
                    if (grid[i][j] == '.')
                    {
                        optpts[i] += 2;
                        if (i < j)
                        {
                            totalP += 2;
                            mf.Add(mf.Source, ind[i, j], 2);
                            mf.Add(ind[i, j], i, 2);
                            mf.Add(ind[i, j], j, 2);
                        }
                    }
                    else if (grid[i][j] == '1')
                    {
                        pts[i] += 2;
                    }
                    else if (grid[i][j] == 'd')
                    {
                        pts[i] += 1;
                    }
                }
            }
            List <int> canWin = new List <int>();
            for (int i = 0; i < N; i++)
            {
                bool ok = true;
                for (int j = 0; j < N; j++)
                {
                    if (j == i)
                    {
                        mf.Capacity[j, mf.Sink] = optpts[i];
                    }
                    else
                    {
                        mf.Capacity[j, mf.Sink] = pts[i] + optpts[i] - pts[j];
                        ok &= mf.Capacity[j, mf.Sink] >= 0;
                    }
                }
                if (ok && mf.NetworkFlow() == totalP)
                {
                    canWin.Add(i + 1);
                }
            }
            Console.WriteLine(string.Join(" ", canWin.Select(i => i.ToString()).ToArray()));
        }
    }
コード例 #29
0
    void Calc()
    {
        int N = int.Parse(Console.ReadLine());

        string[] str = Console.ReadLine().Split(' ');
        int[]    X   = new int[N];
        for (int i = 0; i < N; i++)
        {
            X[i] = int.Parse(str[i]);
        }
        List <int> Diff = new List <int>();

        Diff.Add(X[0]);
        Diff.Add(X[N - 1] + 1);
        for (int i = 1; i < N; i++)
        {
            if (X[i] != X[i - 1] + 1)
            {
                Diff.Add(X[i]);
            }
        }
        for (int i = 0; i < N - 1; i++)
        {
            if (X[i] + 1 != X[i + 1])
            {
                Diff.Add(X[i] + 1);
            }
        }
        int[] diff = Diff.ToArray();
        int   o    = 0;
        int   e    = 0;

        for (int i = 0; i < diff.Length; i++)
        {
            if (diff[i] % 2 == 0)
            {
                e++;
            }
            else
            {
                o++;
            }
        }
        int[] Odd  = new int[o];
        int[] Even = new int[e];
        o = 0;
        e = 0;
        for (int i = 0; i < diff.Length; i++)
        {
            if (diff[i] % 2 == 0)
            {
                Even[e] = diff[i];
                e++;
            }
            else
            {
                Odd[o] = diff[i];
                o++;
            }
        }
        List <int>  f    = new List <int>();
        List <int>  t    = new List <int>();
        List <long> capa = new List <long>();
        int         S    = 0;
        int         Ef   = 1;
        int         Of   = e + 1;
        int         T    = o + e + 1;

        for (int i = 0; i < e; i++)
        {
            f.Add(S);
            t.Add(Ef + i);
            capa.Add(1);
        }
        for (int i = 0; i < o; i++)
        {
            f.Add(Of + i);
            t.Add(T);
            capa.Add(1);
        }
        Generateprimenumber G = new Generateprimenumber(10000);

        for (int i = 0; i < e; i++)
        {
            for (int j = 0; j < o; j++)
            {
                if (G.Prime(Math.Max(Even[i] - Odd[j], Odd[j] - Even[i])))
                {
                    f.Add(Ef + i);
                    t.Add(Of + j);
                    capa.Add(1);
                }
            }
        }
        MaxFlow Flow  = new MaxFlow(f.ToArray(), t.ToArray(), capa.ToArray(), o + e + 2, 0, o + e + 1);
        int     flow  = (int)Flow.flow;
        int     count = diff.Length - flow;

        if (e % 2 != flow % 2)
        {
            count++;
        }
        sb.Append(count + "\n");
    }
コード例 #30
0
        /// <summary>
        /// Wyznacza maksymalny przepływ o minimalnym koszcie
        /// </summary>
        /// <param name="g">Graf przepustowości</param>
        /// <param name="c">Graf kosztów</param>
        /// <param name="source">Wierzchołek źródłowy</param>
        /// <param name="target">Wierzchołek docelowy</param>
        /// <param name="parallel">Informacja czy algorytm ma korzystać z równoległej wersji algorytmu Forda-Bellmana</param>
        /// <param name="mf">Metoda wyznaczania wstępnego maksymalnego przepływu (bez uwzględniania kosztów)</param>
        /// <param name="af">Metoda powiększania przepływu</param>
        /// <param name="matrixToAVL">Czy optymalizować sposób reprezentacji grafu rezydualnego</param>
        /// <returns>
        /// Krotka (value, cost, flow) składająca się z
        /// wartości maksymalnego przepływu, jego kosztu i grafu opisującego ten przepływ
        /// </returns>
        /// <exception cref="ArgumentException"></exception>
        /// <remarks>
        /// Można wybrać metodę wyznaczania wstępnego maksymalnego przepływu (parametr mf).<para/>
        /// Domyślna wartość mf (null) oznacza konstrukcję wstępnego przepływu z wykorzystaniem sztucznej krawędzi.<para/>
        /// Można wybrać metodę powiększania przepływu (parametr pf).<para/>
        /// Znaczenie tego parametru zależy od wybranej metody wyznaczania wstępnego maksymalnego przepływu
        /// (parametr mf), dla niektórych wartości parametru mf
        /// (np. <see cref="MaxFlowGraphExtender.FordFulkersonDinicMaxFlow"/>)
        /// jawne wskazanie metody powiększania przepływu jest konieczne
        /// (pozostawienie domyślnej wartości parametru pf (null)
        /// spowoduje zgłoszenie wyjątku <see cref="ArgumentException"/>).<para/>
        /// Metoda uruchomiona dla grafu nieskierowanego lub grafu
        /// z ujemnymi przepustowościami krawędzi zgłasza wyjątek <see cref="ArgumentException"/>.<para/>
        /// Gdy grafy przepustowości i kosztów mają różną strukturę lub parametry
        /// source i target są równe metoda również zgłasza wyjątek <see cref="ArgumentException"/>.<para/>
        /// Gdy w grafie przepustowości istnieją krawędzie w obu kierunkach
        /// pomiędzy parą wierzchołków metoda również zgłasza wyjątek <see cref="ArgumentException"/>.
        /// </remarks>
        /// <seealso cref="MinCostFlowGraphExtender"/>
        /// <seealso cref="ASD.Graphs"/>
        public static (double value, double cost, Graph flow) MinCostFlow(this Graph g, Graph c, int source, int target, bool parallel = false, MaxFlow mf = null, AugmentFlow af = null, bool matrixToAVL = true)
        {
            if (!g.Directed)
            {
                throw new ArgumentException("Undirected graphs are not allowed");
            }
            if (source == target)
            {
                throw new ArgumentException("Source and target must be different");
            }
            if (g.VerticesCount != c.VerticesCount)
            {
                throw new ArgumentException("Inconsistent capacity and cost graphs");
            }

            var fordBellmanShortestPaths = parallel ? ShortestPathsGraphExtender.FordBellmanShortestPathsParallel : new FordBellmanShortestPaths(ShortestPathsGraphExtender.FordBellmanShortestPaths);

            var gOut = new HashSet <int>();
            var cOut = new HashSet <int>();

            for (var i = 0; i < g.VerticesCount; i++)
            {
                gOut.Clear();
                cOut.Clear();
                foreach (var edge in g.OutEdges(i))
                {
                    if (edge.Weight < 0.0)
                    {
                        throw new ArgumentException("Negative capacity edges are not allowed");
                    }
                    if (!g.GetEdgeWeight(edge.To, edge.From).IsNaN())
                    {
                        throw new ArgumentException(
                                  "Edges in both directions between pair of vertices are not allowed");
                    }
                    gOut.Add(edge.To);
                }

                foreach (var edge in c.OutEdges(i))
                {
                    cOut.Add(edge.To);
                }

                if (!gOut.SetEquals(cOut))
                {
                    throw new ArgumentException("Inconsistent capacity and cost graphs");
                }
            }

            var   tempCost = double.NaN;
            var   tempFlow = double.NaN;
            var   maxFlow  = double.NaN;
            Graph flow;

            if (mf != null)
            {
                (maxFlow, flow) = mf(g, source, target, af, matrixToAVL);
            }
            else
            {
                if (!(tempFlow = g.GetEdgeWeight(source, target)).IsNaN())
                {
                    g.DelEdge(source, target);
                }
                if (!(tempCost = c.GetEdgeWeight(source, target)).IsNaN())
                {
                    c.DelEdge(source, target);
                }
                flow = g.IsolatedVerticesGraph();
                var maxPossibleFlow = g.OutEdges(source).Sum(e => e.Weight);
                g.AddEdge(source, target, maxPossibleFlow + 1.0);
                flow.AddEdge(source, target, maxPossibleFlow + 1.0);
                var maxPossibleCost = 0.0;
                for (var i = 0; i < c.VerticesCount; i++)
                {
                    foreach (var edge4 in c.OutEdges(i))
                    {
                        maxPossibleCost += Math.Abs(edge4.Weight);
                        flow.AddEdge(edge4.From, edge4.To, 0.0);
                    }
                }
                c.AddEdge(source, target, maxPossibleCost + 1.0);
            }

            var residualFlow = flow.IsolatedVerticesGraph();
            var residualCost = flow.IsolatedVerticesGraph();

            for (var i = 0; i < flow.VerticesCount; i++)
            {
                foreach (var edge in flow.OutEdges(i))
                {
                    var something = Math.Min(g.GetEdgeWeight(edge.From, edge.To), double.MaxValue) - edge.Weight;
                    if (something > 0.0)
                    {
                        residualFlow.AddEdge(edge.From, edge.To, something);
                        residualCost.AddEdge(edge.From, edge.To, c.GetEdgeWeight(edge.From, edge.To));
                    }

                    if (edge.Weight > 0.0)
                    {
                        residualFlow.AddEdge(edge.To, edge.From, edge.Weight);
                        residualCost.AddEdge(edge.To, edge.From, -c.GetEdgeWeight(edge.From, edge.To));
                    }
                }
            }

            var foundFlow = 0.0;

            while (!fordBellmanShortestPaths(residualCost, target, out var pi))
            {
                var cycle        = residualCost.FindNegativeCostCycle(pi).cycle;
                var cycleMaxFlow = double.PositiveInfinity;
                var flag         = false;
                foreach (var edge in cycle)
                {
                    if (edge.From == target && edge.To == source)
                    {
                        flag = true;
                    }
                    var weight = residualFlow.GetEdgeWeight(edge.From, edge.To);
                    if (cycleMaxFlow > weight)
                    {
                        cycleMaxFlow = weight;
                    }
                }
                if (flag)
                {
                    foundFlow += cycleMaxFlow;
                }
                foreach (var edge in cycle)
                {
                    if (flag = (flow.GetEdgeWeight(edge.To, edge.From) > 0.0))
                    {
                        var weight = flow.ModifyEdgeWeight(edge.To, edge.From, -cycleMaxFlow);
                        if (weight < 0.0)
                        {
                            flow.ModifyEdgeWeight(edge.To, edge.From, -weight);
                            flow.ModifyEdgeWeight(edge.From, edge.To, -weight);
                        }
                    }
                    else
                    {
                        flow.ModifyEdgeWeight(edge.From, edge.To, cycleMaxFlow);
                    }

                    if (residualFlow.ModifyEdgeWeight(edge.From, edge.To, -cycleMaxFlow) == 0.0)
                    {
                        residualFlow.DelEdge(edge);
                        residualCost.DelEdge(edge);
                    }

                    if (residualFlow.ModifyEdgeWeight(edge.To, edge.From, cycleMaxFlow).IsNaN())
                    {
                        residualFlow.AddEdge(edge.To, edge.From, cycleMaxFlow);
                        var weight = (flag ? c.GetEdgeWeight(edge.To, edge.From) : c.GetEdgeWeight(edge.From, edge.To));
                        residualCost.AddEdge(edge.To, edge.From, flag ? weight : (-weight));
                    }
                }
            }
            if (mf == null)
            {
                g.DelEdge(source, target);
                c.DelEdge(source, target);
                flow.DelEdge(source, target);
                if (!tempFlow.IsNaN())
                {
                    foundFlow += tempFlow;
                    g.AddEdge(source, target, tempFlow);
                    c.AddEdge(source, target, tempCost);
                    flow.AddEdge(source, target, tempFlow);
                }
                maxFlow = foundFlow;
            }
            var cost = 0.0;

            for (var k = 0; k < flow.VerticesCount; k++)
            {
                cost += flow.OutEdges(k).Sum(e => e.Weight * c.GetEdgeWeight(e.From, e.To));
            }
            return(maxFlow, cost, flow);
        }
コード例 #31
0
ファイル: 1302678.cs プロジェクト: qifanyyy/CLCDSA
    void Calc()
    {
        string[]    str   = Console.ReadLine().Split(' ');
        int         H     = int.Parse(str[0]);
        int         W     = int.Parse(str[1]);
        int         S     = -1;
        int         G     = -1;
        int         si    = -1;
        int         sj    = -1;
        int         gi    = -1;
        int         gj    = -1;
        List <int>  f     = new List <int>();
        List <int>  t     = new List <int>();
        List <long> c     = new List <long>();
        int         count = H + W;

        for (int i = 0; i < H; i++)
        {
            string s = Console.ReadLine();
            for (int j = 0; j < W; j++)
            {
                if (s[j] != '.')
                {
                    f.Add(count);
                    t.Add(i);
                    f.Add(count);
                    t.Add(H + j);
                    if (s[j] == 'S')
                    {
                        S = count;
                        c.Add(1000000000);
                        c.Add(1000000000);
                        si = i;
                        sj = j;
                    }
                    else if (s[j] == 'T')
                    {
                        G = count;
                        c.Add(1000000000);
                        c.Add(1000000000);
                        gi = i;
                        gj = j;
                    }
                    else
                    {
                        c.Add(1);
                        c.Add(1);
                    }
                    count++;
                }
            }
        }
        if (si == gi || sj == gj)
        {
            sb.Append("-1\n");
            return;
        }
        MaxFlow F = new MaxFlow(f.ToArray(), t.ToArray(), c.ToArray(), count, S, G);

        sb.Append(F.flow + "\n");
    }