题目大意
- 给出n*n的矩形,k个点。每次可选择删除一行或一列的点,求至少需要删除几次方可将点全部删除。
分析
- 构造有向二分图:把每行x或者每列y看成一个点,而障碍物(x,y)可以看做连接x和y的边。
- 问题就转化成为选择最少的一些点(x或y),使得从这些点与所有的边相邻,其实这就是最小点覆盖问题。
- Konig定理: 最小点覆盖数 = 最大匹配数
- 用匈牙利算法求二分图的最大匹配即可
代码
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 510;
int g[maxn][maxn] , n , k;
int vis[maxn] , match[maxn];
bool find(int x)
{
for(int i = 1; i <= n; i++) if(g[x][i] && !vis[i]) {
vis[i] = 1;
if(!match[i] || find(match[i])) {
match[i] = x;
return true;
}
}
return false;
}
int main()
{
while(cin >> n >> k)
{
memset(g , 0 , sizeof(g));
for(int i = 0; i < k; i++) {
int x , y;
cin >> x >> y;
g[x][y] = 1;
}
memset(match , 0 , sizeof(match));
int sum = 0;
for(int i = 1; i <= n; i++) {
memset(vis , 0 , sizeof(vis));
if(find(i)) sum++;
}
cout << sum << endl;
}
return 0;
}