题意:
一个矩阵,其中一些点上有小行星。
一次可以摧毁1行或者1列的全部小行星,问最少几次可以摧毁所有小行星。
思路:
如果在(i, j)这个点上有小行星,则连边i->j。
i与j只要选一个,这条边代表的小行星就会被摧毁。
可见,本题答案就是最小点覆盖,即选择最少的点,使每条边都至少有一个端点被选中。
二分图中最小点覆盖=最大匹配
代码(736K,16MS):
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int n, m;
vector<int> edges[505];
int mat[505];
int vis[505];
bool dfs(int k) {
for (int i = 0; i < edges[k].size(); i++) {
int j = edges[k][i];
if (!vis[j]) {
vis[j] = 1;
if (!mat[j] || dfs(mat[j])) {
mat[j] = k;
return true;
}
}
}
return false;
}
int match() {
int ans = 0;
memset(mat, 0, sizeof(mat));
for (int i = 1; i <= n; i++) {
memset(vis, 0, sizeof(vis));
if (dfs(i)) ans++;
}
return ans;
}
int main() {
while (~scanf("%d %d", &n, &m)) {
for (int i = 1; i <= n; i++)
edges[i].clear();
int a, b;
for (int i = 0; i < m; i++) {
scanf("%d %d", &a, &b);
edges[a].push_back(b);
}
printf("%d\n", match());
}
return 0;
}