示例#1
0
        // DFS
        static bool TryMatching(int left,
                                BipartiteGraph G,
                                IDictionary <int, int> toMatchedRight,
                                IDictionary <int, int> toMatchedLeft,
                                IDictionary <int, long> distances)
        {
            if (left == 0)
            {
                return(true);
            }

            foreach (var right in G.Edge(left))
            {
                var nextLeft = toMatchedLeft[right];
                if (distances[nextLeft] == distances[left] + 1)
                {
                    if (TryMatching(nextLeft, G, toMatchedRight, toMatchedLeft, distances))
                    {
                        toMatchedLeft[right] = left;
                        toMatchedRight[left] = right;
                        return(true);
                    }
                }
            }

            // The left could not match any right.
            distances[left] = long.MaxValue;

            return(false);
        }
示例#2
0
        //static void Main()
        //{
        //    var lefts = new HashSet<int> { 1, 2, 3, 4, 5 };
        //    var rights = new HashSet<int> { 6, 7, 8, 9, 10 };

        //    var edges = new Dictionary<int, HashSet<int>>
        //    {
        //        [1] = new HashSet<int> { 6, 7 },
        //        [2] = new HashSet<int> { 6, 10 },
        //        [3] = new HashSet<int> { 8, 9 },
        //        [4] = new HashSet<int> { 6, 10 },
        //        [5] = new HashSet<int> { 7, 9 }
        //    };

        //    var matches = HopcroftKarpFunction(lefts, rights, edges);

        //    Console.WriteLine($"# of matches: {matches.Count}\n");

        //    foreach (var match in matches)
        //    {
        //        Console.WriteLine($"Match: {match.Key} -> {match.Value}");
        //    }
        //}

        //public static Func<int, HashSet<int>> EdgeDelegate = BipartiteGraph.Edge;

        // BFS
        static bool HasAugmentingPath(IEnumerable <int> lefts,
                                      BipartiteGraph G,
                                      IReadOnlyDictionary <int, int> toMatchedRight,
                                      IReadOnlyDictionary <int, int> toMatchedLeft,
                                      IDictionary <int, long> distances,
                                      Queue <int> q)
        {
            foreach (var left in lefts)
            {
                if (toMatchedRight[left] == 0)
                {
                    distances[left] = 0;
                    q.Enqueue(left);
                }
                else
                {
                    distances[left] = long.MaxValue;
                }
            }

            distances[0] = long.MaxValue;

            while (0 < q.Count)
            {
                var left = q.Dequeue();

                if (distances[left] < distances[0])
                {
                    foreach (var right in G.Edge(left))
                    {
                        var nextLeft = toMatchedLeft[right];
                        if (distances[nextLeft] == long.MaxValue)
                        {
                            // The nextLeft has not been visited and is being visited.
                            distances[nextLeft] = distances[left] + 1;
                            q.Enqueue(nextLeft);
                        }
                    }
                }
            }

            return(distances[0] != long.MaxValue);
        }