POJ-3041 Asteroids 二分图匹配

该题题义为给定网格的中的点的坐标,现在要去将这些点摧毁,有一种武器能够一次摧毁一行或者是一列的所有目标,问最少用多少次该武器能够使得所有的目标消失。

这题怎么转化为二分图去做呢,过程是这样的,首先对于每个目标有两种方式能够让其消失,一种是在其所在行上使用武器,一种是在其所在列上使用武器。那么对于所有的目标而言,只要在行列满足之一的地方使用武器就可以全部清除目标。于是我们可以将目标所在行列进行匹配,然后再求最小顶点覆盖就可以了。因为最小顶点覆盖就是满足一条边至少有一个顶点在这个顶点集中。

代码如下:

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 1000
using namespace std;

int N, M, match[MAXN], visit[MAXN];
int G[MAXN][MAXN];

bool path(int u)
{
    // visit[u] = 1;
    // 上式是错的,visit所使用的对象是与u对应的部分,所以不能在这一标记
    for (int i = 1; i <= N; ++i) {
        if (!G[u][i] || visit[i]) {
            continue;
        }
        visit[i] = 1; // 考虑应该是y部的访问情况
        if (!match[i] || path(match[i])) {
            match[i] = u;
            return true;
        }
    }
    return false;
}

int main()
{
    int x, y, ans = 0;
    scanf("%d %d", &N, &M);
    for (int i = 1; i <= M; ++i) {
        scanf("%d %d", &x, &y);
        G[x][y] = 1;
    }
    for (int i = 1; i <= N; ++i) { 
        memset(visit, 0, sizeof (visit));
        if (path(i)) {
            ++ans;
        }
    }
    printf("%d\n", ans);
    return 0; 
}
posted @ 2012-07-02 16:51  沐阳  阅读(192)  评论(0编辑  收藏  举报