POJ 3041_Asteroids

题意:

N*N网格中有小行星,光束能将一整行或者一整列的行星消灭,问消灭所有行星至少需要多少光束?

分析:

最小顶点覆盖问题,将每个小行星看成边,左右顶点为横纵坐标,可以转化为二分图,利用二分图中最小顶点覆盖等于最大二分匹配的性质,求出最大二分匹配(匈牙利算法)即可。

代码:

#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
const int maxn = 10005;
int x[maxn], y[maxn];
int used[maxn], match[maxn];
int N, K;
vector<int>G[maxn];
void add_edge(int u, int v)
{
    G[v].push_back(u);
    G[u].push_back(v);
}
int dfs(int v)
{
    used[v] = 1;
    for(int i = 0; i < G[v].size(); i++){
        int u = G[v][i], w = match[u];
        if(w<0||!used[w]&&dfs(w)){
            match[v] = u;
            match[u] = v;
            return 1;
        }
    }
    return 0;
}
int bipartite_matching()
{
    int res = 0;
    memset(match, -1, sizeof(match));
    for(int i = 1; i <= 2 * N; i++){
        if(match[i]<0){
            memset(used, 0, sizeof(used));
            if(dfs(i))
                res++;
        }
    }
    return res;
}
int main (void)
{
   scanf("%d%d",&N,&K);
    memset(match, -1, sizeof(match));
    for(int i = 0; i < K; i++){
        scanf("%d%d",&x[i],&y[i]);
        add_edge(x[i], y[i] + N);
    }
    printf("%d\n",  bipartite_matching());
}

你可能感兴趣的:(POJ 3041_Asteroids)