POJ 3041 Asteroids
最小点覆盖:选择一个点能够与它相连的所有边,选择一个最小的点集能够覆盖二分图中所有的边。
最小点覆盖==最大匹配
匈牙利算法求解
#include <iostream>
#include <cstdio>
#include <cstring>
#define INF 0x3f3f3f3f
#define lowbit(x) x & (-x)
using namespace std;
typedef long long ll;
const int maxN = 505;
const int maxK = 10004;
const ll mod = 1e9+9;
int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-') f = -f; ch = getchar(); }
while(ch >= '0' && ch <= '9') {
x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
int n, k;
bool used[maxN], match[maxN][maxN];
int Left[maxN];
bool Hungary(int x) {
for(int i = 1; i <= n; ++ i ) {
if(match[x][i] && !used[i]) {
used[i] = true;
if(Left[i] == 0 || Hungary(Left[i])) {
Left[i] = x;
return true;
}
}
}
return false;
}
int main() {
n = read(); k = read();
for(int i = 0; i < k; ++ i ) {
int x, y; x = read(); y = read();
match[x][y] = true;
}
int ans = 0;
for(int i = 1; i <= n; ++ i ) {
memset(used, false, sizeof(used));
if(Hungary(i)) ++ ans;
}
cout << ans << endl;
return 0;
}
最小点覆盖的点是哪些?
是从一个右边未被匹配的点出发走增广路,标记增广路上的所有点。走完所有的增广路的点之后,右边未被标记的点以及左边被标记的点就是最小覆盖点集。