POJ-3041 行列匹配构图+最小顶点覆盖
题意:给定一个网格,现在某些格子坐标中有一个小行星,现有一种武器能够击穿一行或者是一列的小行星,问最少使用多少次这种武器能够销毁所有的小行星。
解法:由于每一个点只要被行或者列覆盖到就可以,因此可以将某一点所在的行和列进行匹配,问题就转化为求一个最小顶点覆盖就可以了,因为这样能够保证每一条边都有一个顶点在点集内。也即每个小行星都能够被所在的行或者是所在的列覆盖到。
代码如下:
#include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> #include <algorithm> using namespace std; int N, M; char G[505][505], vis[505]; int match[505]; int path(int u) { for (int i = 1; i <= N; ++i) { if (!G[u][i] || vis[i]) continue; vis[i] = 1; if (!match[i] || path(match[i])) { match[i] = u; return 1; } } return 0; } int query() { int ret = 0; memset(match, 0, sizeof (match)); for (int i = 1; i <= N; ++i) { memset(vis, 0, sizeof (vis)); ret += path(i); } return ret; } int main() { int a, b; while (scanf("%d %d", &N, &M) != EOF) { for (int i = 0; i < M; ++i) { scanf("%d %d", &a, &b); G[a][b] = 1; // 行列匹配构图,最后求一个最小顶点覆盖 } printf("%d\n", query()); } return 0; }