poj3041二分图最优匹配

http://poj.org/problem?id=3041

本题我看了很长时间,但直到看了别人的解题思路才知道是二分图最优匹配o(╯□╰)o........

((((((转载请注明出处:優YoU http://user.qzone.qq.com/289065406/blog/1299322465

解题思路:把方阵看做一个特殊的二分图(以行列分别作为两个顶点集V1、V2,其中| V1|=| V2|)

然后把每行x或者每列y看成一个点,而障碍物(x,y)可以看做连接x和y的边。按照这种思路构图后。问题就转化成为选择最少的一些点(x或y),使得从这些点与所有的边相邻,其实这就是最小点覆盖问题。

再利用二分图最大匹配的König定理:

最小点覆盖数 = 最大匹配数   PS:最小点覆盖:假如选了一个点就相当于覆盖了以它为端点的所有边,你需要选择最少的点来覆盖图的所有的边。

因此本题自然转化为求 二分图的最大匹配 问题))))))))

代码是我自己的。。。。。

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int g[550][550];
int vis[550];
int dis[550];
int n,k;

int match(int i)
{
    for(int j=1;j<=n;j++)
    {
        if(vis[j]==-1&&g[i][j]==1)
        {
            vis[j]=1;
            if(dis[j]==-1||match(dis[j])==1)
            {
                dis[j]=i;
                return 1;
            }
        }
    }
    return 0;
}

int MMG()
{
    int sum=0;
    memset(dis,-1,sizeof(dis));
    for(int i=1;i<=n;i++)
    {
        memset(vis ,-1,sizeof(vis));
        if(match(i))sum++;
    }
    return sum;
}

int main()
{
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        int x,y;
        for(int i=1;i<=k;i++)
        {
            scanf("%d%d",&x,&y);
            g[x][y]=1;
        }
        printf("%d\n",MMG());
    }
    return 0;
}
View Code

 

posted @ 2013-08-12 19:57  拼搏今朝 努力奋进  阅读(185)  评论(0)    收藏  举报