题意
在一个 N × N N\times N N×N的网格上,分布着 K K K个行星。
Bessie拥有一种能力,每次可以消灭一行或一列的行星。
求Bessie最少需要多少次才可以消灭所有的行星。
输入
输入
N
,
K
N, K
N,K。
接下来
K
K
K行,每行输入2个整数
x
,
y
x, y
x,y,表示一个行星的坐标。
输出
输出最少的次数
思路
把每行、每列都当作一个节点,网格中的点看作这些节点的边,即若有一个点的坐标是 ( 2 , 3 ) (2, 3) (2,3),则认为第2行和第3列有一条边。
问题就转换成求最小点覆盖问题。最少需要多少个节点就可以覆盖所有的边。
根据最小割定理可以知道,最小点覆盖问题等价于最大匹配问题。
代码
#include <iostream>
#include <vector>
#include <string>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <set>
using namespace std;
const int N = 1e3 + 10;
vector<int> g[N];
int c[N];
bool vis[N];
bool dfs(int u) {
for (int i = 0; i < g[u].size(); i++) {
int v = g[u][i];
if (vis[v])
continue;
vis[v] = true;
if (c[v] == -1 || dfs(c[v])) {
c[v] = u;
return true;
}
}
return false;
}
int main() {
int n, k, t;
scanf("%d%d", &n, &k);
for (int i = 0; i < k; i++) {
int x, y;
scanf("%d%d", &x, &y);
g[x].push_back(y + n);
g[y + n].push_back(x);
}
memset(c, -1, sizeof(c));
int res = 0;
for (int i = 1; i <= n; i++) {
memset(vis, false, sizeof(vis));
if (dfs(i))
res = res + 1;
}
printf("%d\n", res);
return 0;
}