// 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); }
//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); }