Implements Hopcroft Karp algorithm for finding maximum matching for unweighted undirected bipartiate graphs https://en.wikipedia.org/wiki/Hopcroft%E2%80%93Karp_algorithm
示例#1
0
    static void Main()
    {
        int n     = int.Parse(Console.ReadLine());
        var reds  = new Point[n + 1]; // 0????
        var blues = new Point[n + 1]; // 0????

        for (int i = 1; i <= n; i++)
        {
            var vals = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
            reds[i] = new Point(vals[0], vals[1]);
        }
        for (int i = 1; i <= n; i++)
        {
            var vals = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
            blues[i] = new Point(vals[0], vals[1]);
        }

        var link = new List <int> [n + 1];

        for (int i = 1; i <= n; i++)
        {
            link[i] = new List <int>();
            var red = reds[i];
            for (int j = 1; j <= n; j++)
            {
                var blue = blues[j];
                if (red.X < blue.X && red.Y < blue.Y)
                {
                    link[i].Add(j);
                }
            }
        }

        Console.WriteLine(HopcroftKarp.GetMaxMatch(n, n, link));
    }
示例#2
0
    /** 
     * Unit tests the {@code HopcroftKarp} data type.   
     * Takes three command-line arguments {@code V1}, {@code V2}, and {@code E};
     * creates a random bipartite graph with {@code V1} + {@code V2} vertices
     * and {@code E} edges; computes a maximum matching and minimum vertex cover;
     * and prints the results.
     *
     * @param args the command-line arguments
     */
    public static void main(String[] args) {

        int V1 = Integer.parseInt(args[0]);
        int V2 = Integer.parseInt(args[1]);
        int E  = Integer.parseInt(args[2]);
        Graph G = GraphGenerator.bipartite(V1, V2, E);
        if (G.V() < 1000) StdOut.println(G);

        HopcroftKarp matching = new HopcroftKarp(G);

        // print maximum matching
        StdOut.printf("Number of edges in max matching        = %d\n", matching.size());
        StdOut.printf("Number of vertices in min vertex cover = %d\n", matching.size());
        StdOut.printf("Graph has a perfect matching           = %b\n", matching.isPerfect());
        StdOut.println();

        if (G.V() >= 1000) return;

        StdOut.print("Max matching: ");
        for (int v = 0; v < G.V(); v++) {
            int w = matching.mate(v);
            if (matching.isMatched(v) && v < w)  // print each edge only once
                StdOut.print(v + "-" + w + " ");
        }
        StdOut.println();

        // print minimum vertex cover
        StdOut.print("Min vertex cover: ");
        for (int v = 0; v < G.V(); v++)
            if (matching.inMinVertexCover(v))
                StdOut.print(v + " ");
        StdOut.println();
    }
示例#3
0
        public void Trivial()
        {
            var sut   = new HopcroftKarp();
            var graph = new int[4][];

            graph[0] = new[] { 0, 1, 0, 0 };
            graph[1] = new[] { 1, 0, 0, 0 };
            graph[2] = new[] { 0, 0, 0, 1 };
            graph[3] = new[] { 0, 0, 1, 0 };

            Assert.Equal(2, sut.GetMaxMatching(graph));
        }
示例#4
0
        public void ComplexBaseline()
        {
            var sut   = new HopcroftKarp();
            var graph = new int[8][];

            graph[0] = new[] { 0, 1, 0, 1, 0, 0, 0, 1 };
            graph[1] = new[] { 1, 0, 1, 0, 0, 0, 1, 0 };
            graph[2] = new[] { 0, 1, 0, 0, 0, 0, 0, 0 };
            graph[3] = new[] { 1, 0, 0, 0, 1, 0, 0, 0 };
            graph[4] = new[] { 0, 0, 0, 1, 0, 0, 0, 0 };
            graph[5] = new[] { 0, 0, 0, 0, 0, 0, 1, 0 };
            graph[6] = new[] { 0, 1, 0, 1, 0, 1, 0, 1 };
            graph[7] = new[] { 1, 0, 0, 0, 0, 0, 1, 0 };

            Assert.Equal(4, sut.GetMaxMatching(graph));
        }
示例#5
0
 public void SetUp()
 {
     hopcroftKarp = new HopcroftKarp <int>();
 }
示例#6
0
        public static void Enum_Maximum_Matching(Dictionary <string, List <string> > G)
        {
            //creating adjecency matrix with its values as integers which will be given as input to maximum HopcroftKarp method.
            var matchingInput = new List <int[]>(); //it is the input to the maximum matching method(hopcroftKarp) It contains adjecency matrix in the form of integers
            var modelIntMap   = new Dictionary <string, int>();
            int count         = 0;
            int t             = 0;

            foreach (var elem in G)
            {
                int[] temp = new int[elem.Value.Count];
                foreach (string mod in elem.Value)
                {
                    if (!modelIntMap.Keys.Contains(mod))
                    {
                        modelIntMap.Add(mod, count++);
                    }
                    temp[t++] = modelIntMap[mod]; //here array is created i.e. row of adjecancy matrix
                }
                matchingInput.Add(temp);          //here the array created above is added to the adjecency list( a representation of adjecency matrix representation)
                t = 0;
            } // at the end of this for loop there is a adjecency list containing integers as its elements and a dictionary of mapping is created to store information of
              //these integers and to which model these intergers are mapped to "modelIntMap< name of model, integer associated to model>"

            var varIntMap = new Dictionary <string, int>();

            count = modelIntMap.Count; //reassigned value of "count" variable
            foreach (var elem in G)
            {
                if (!varIntMap.Keys.Contains(elem.Key))
                {
                    varIntMap.Add(elem.Key, count++);
                }
            }

            //Step1: Finding a maximum matching M of G and output M.
            var matching = HopcroftKarp.GetMatching(matchingInput, modelIntMap.Count); //here "matching" stores the matched variables on right of bipartite graph
                                                                                       /* Here matching obtained above is used to create matched edges as list containing two integers ..first int is source location while second destination for a link/edge*/

            /* List<List<int>> matchingEdges = new List<List<int>>();
             * int inc = 0;
             * foreach (var match in matching)
             * {
             *   List<int> temp = new List<int>();
             *   temp.Add(match);
             *   temp.Add(varIntMap.Values.ElementAt(inc));
             *   matchingEdges.Add(temp);
             * }*/
            var matchingEdges = new List <string>();
            int inc           = 0;

            foreach (var match in matching)
            {
                if (!(match < 0))
                {
                    matchingEdges.Add(varIntMap.Values.ElementAt(inc++).ToString() + match.ToString());
                }
            }

            Dictionary <int, List <int> > UnDirectBGInt = UndirectedGraphStringsToInt(G, modelIntMap, varIntMap);

            int[,] DirectedBGEdges = DirectedGraph(UnDirectBGInt, matchingEdges);
            var g    = new Tarjan(DirectedBGEdges);
            var SCCs = g.GetStronglyConnectedComponents();

            //g = new Tarjan(new[,] {
            //    {1, 2}, {2, 3}, {2, 4}, {2, 5}, {3, 1}, {4, 1}, {4, 6}, {4, 8}, {5, 6}, {6, 7}, {7, 5}, {8, 6}
            //});
            //g = new Tarjan(new[,] {
            //    {1, 2}, {2,3 }, {3, 1}, {3, 4}, {4, 5}, {5, 6}, {6, 3}
            //});
            g = new Tarjan(new[, ] {
                { 1, 2 }, { 2, 3 }, { 3, 1 }, { 4, 3 }, { 5, 4 }, { 6, 5 }, { 3, 6 }
            });
            SCCs = g.GetStronglyConnectedComponents();

            //Step2: Trim unnecessary arcs from D(G,M) by a strongly connected component decomposition algorithm.


            //Step:3 Call Enum_Maximum_Matching_Iter(G,M,D(G,M))
        }