This problem can be efficiently solved using the Hungarian Algorithm, a combinatorial optimization algorithm that finds a maximum matching in a bipartite graph. A bipartite graph is a graph whose vertices can be divided into two disjoint sets, such that every edge connects a vertex in one set to a vertex in the other set. In this problem:
grid[i][j] == 1
(the i-th boy can invite the j-th girl).The goal is to find the maximum number of edges (invitations) such that no boy invites more than one girl and no girl receives more than one invitation. This is precisely what the Hungarian algorithm solves.
The Hungarian algorithm iteratively searches for augmenting paths. An augmenting path is a path in the graph that starts at an unmatched boy and ends at an unmatched girl, alternating between unmatched boys and girls. Finding such a path allows us to increase the number of matched pairs (invitations).
The algorithm follows these steps:
Initialization: Create a match
array to store the girl each boy is matched with (-1 indicates unmatched).
Iteration: For each boy:
vis
(visited) set to track visited girls during the search for an augmenting path.find(i)
to search for an augmenting path starting from boy i
.Recursive find(i)
function:
j
that boy i
can invite (grid[i][j] == 1
):
j
not in vis
):
vis.add(j)
).match[j] == -1
) or if we can find an augmenting path from the boy currently matched with this girl (find(match[j])
):
i
with the girl j
(match[j] = i
).True
(augmenting path found).False
(no augmenting path found from this boy).Counting Matches: After iterating through all boys, the number of matched pairs (ans
) represents the maximum number of accepted invitations.
The Hungarian algorithm has a time complexity of approximately O(m*n) in its optimized implementations, where 'm' is the number of boys and 'n' is the number of girls. This is because in the worst case, the algorithm might explore all possible edges in the bipartite graph. In practice, it often performs much faster due to the efficiency of augmenting path searches.
The space complexity is O(m + n), primarily due to the match
array and the vis
set (in some implementations). These data structures store information about the matching and visited nodes during the search for augmenting paths.
The code examples provided earlier demonstrate the Hungarian Algorithm in Python, Java, C++, and Go. The structure and logic are very similar across languages; the main differences lie in syntax and data structure implementations. The core idea of iteratively finding augmenting paths remains consistent.