poj3041 建图+最小顶点覆盖(最大匹配数)

  这个题的意思是给你一个N*N的矩阵, 里面有K个星球, 我们可以让武器攻击矩阵的一行或者一列来使得这个星球被击碎, 现在问你最少需要几个这种武器才能把所有的星球击碎, 首先我们可以知道每个武器最多攻击一行一次, 因此最多有2*N个武器, 另外我们可以将武器看成顶点, 星球看成边,连接一副图,求出这个图的最小顶点覆盖数也就是最大匹配数即可, 代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;
const int maxn = 1000+10;

struct Hungarian
{
    int n;    //顶点的数量
    int match[maxn];
    int check[maxn];
    vector<int> G[maxn];
    void init()
    {
        for(int i=0; i<=n; i++) G[i].clear();
    }
    void add_edge(int u, int v)
    {
        G[u].push_back(v);
        G[v].push_back(u);
    }
    bool dfs(int u)
    {
        for(int i=0; i<G[u].size(); i++)
        {
            int v = G[u][i];
            if(!check[v])
            {
                check[v] = 1;
                if(match[v]==-1 || dfs(match[v]))
                {
                    match[u] = v;
                    match[v] = u;
                    return true;
                }
            }
        }
        return false;
    }
    int hungarian()
    {
        int ans = 0;
        memset(match, -1, sizeof(match));
        for(int u=1; u<=n; u++)
        {
            if(match[u] == -1)
            {
                memset(check, 0, sizeof(check));
                if(dfs(u)) ++ans;
            }
        }
        return ans;
    }
}hun;

int main()
{
    int N, K;
    scanf("%d%d", &N, &K);
    hun.n = 2*N;
    hun.init();
    for(int i=0; i<K; i++)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        hun.add_edge(u,  v+N);
    }
    printf("%d\n", hun.hungarian());
    return 0;
}

 

posted @ 2016-03-04 20:18  xing-xing  阅读(792)  评论(0编辑  收藏  举报