题目描述
某一个班级有 m
个男孩和 n
个女孩,即将举行一个派对。
给定一个 m x n
的整数矩阵 grid
,其中 grid[i][j]
等于 0
或 1
。 若 grid[i][j] == 1
,则表示第 i
个男孩可以邀请第 j
个女孩参加派对。 一个男孩最多可以邀请一个女孩,一个女孩最多可以接受一个男孩的一个邀请。
返回可能的最多邀请的个数。
示例 1:
输入: grid = [[1,1,1],
[1,0,1],
[0,0,1]]
输出: 3
解释: 按下列方式邀请:
- 第 1 个男孩邀请第 2 个女孩。
- 第 2 个男孩邀请第 1 个女孩。
- 第 3 个男孩邀请第 3 个女孩。
示例 2:
输入: grid = [[1,0,1,0],
[1,0,0,0],
[0,0,1,0],
[1,1,1,0]]
输出: 3
解释: 按下列方式邀请:
- 第 1 个男孩邀请第 3 个女孩。
- 第 2 个男孩邀请第 1 个女孩。
- 第 3 个男孩未邀请任何人。
- 第 4 个男孩邀请第 2 个女孩。
提示:
grid.length == m
grid[i].length == n
1 <= m, n <= 200
grid[i][j]
是 0
或 1
之一。
解法
方法一:匈牙利算法
本题属于二分图最大匹配问题,适合用匈牙利算法来求解。
匈牙利算法的核心思想是,不断地从未匹配的点出发,寻找增广路径,直到没有增广路径为止,就得到了最大匹配。
时间复杂度 $O(m \times n)$。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | class Solution:
def maximumInvitations(self, grid: List[List[int]]) -> int:
def find(i):
for j, v in enumerate(grid[i]):
if v and j not in vis:
vis.add(j)
if match[j] == -1 or find(match[j]):
match[j] = i
return True
return False
m, n = len(grid), len(grid[0])
match = [-1] * n
ans = 0
for i in range(m):
vis = set()
ans += find(i)
return ans
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 | class Solution {
private int[][] grid;
private boolean[] vis;
private int[] match;
private int n;
public int maximumInvitations(int[][] grid) {
int m = grid.length;
n = grid[0].length;
this.grid = grid;
vis = new boolean[n];
match = new int[n];
Arrays.fill(match, -1);
int ans = 0;
for (int i = 0; i < m; ++i) {
Arrays.fill(vis, false);
if (find(i)) {
++ans;
}
}
return ans;
}
private boolean find(int i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == 1 && !vis[j]) {
vis[j] = true;
if (match[j] == -1 || find(match[j])) {
match[j] = i;
return true;
}
}
}
return false;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 | class Solution {
public:
int maximumInvitations(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size();
bool vis[210];
int match[210];
memset(match, -1, sizeof match);
int ans = 0;
function<bool(int)> find = [&](int i) -> bool {
for (int j = 0; j < n; ++j) {
if (grid[i][j] && !vis[j]) {
vis[j] = true;
if (match[j] == -1 || find(match[j])) {
match[j] = i;
return true;
}
}
}
return false;
};
for (int i = 0; i < m; ++i) {
memset(vis, 0, sizeof vis);
ans += find(i);
}
return ans;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 | func maximumInvitations(grid [][]int) int {
m, n := len(grid), len(grid[0])
var vis map[int]bool
match := make([]int, n)
for i := range match {
match[i] = -1
}
var find func(i int) bool
find = func(i int) bool {
for j, v := range grid[i] {
if v == 1 && !vis[j] {
vis[j] = true
if match[j] == -1 || find(match[j]) {
match[j] = i
return true
}
}
}
return false
}
ans := 0
for i := 0; i < m; i++ {
vis = map[int]bool{}
if find(i) {
ans++
}
}
return ans
}
|