二分图匹配的最小覆盖点集问题

//二分图的一些简单想法
//二分图的最小覆盖点:假定选了一个点就相当于覆盖了以它为端点的所有边
//二分图的最小覆盖点集(在 X集合和Y集合中选取最少的点可以将图中所有的边都覆盖)
//最小覆盖点集数 == 二分图的最大匹配数
//结论证明:https://www.cnblogs.com/jianglangcaijin/p/6035945.html (ORZ)
//例题 HDU 2119(板子)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 100 + 15;
bool Grape[maxn][maxn];//思路:以横轴和纵轴建立二分图,if Grape[i][j] == true,则证明i j之间存在边,转换为最小覆盖点集问题
int n,m;
bool vis[maxn];
int match[maxn];
bool Hungary(int u)//寻找增广路
{
    for(int v=1;v<=m;++v)
    {
        if(!vis[v]&&Grape[u][v])
        {
            vis[v] = true;
            if(match[v]==-1||Hungary(match[v]))
            {
                match[v] = u;
                return true;
            }
        }
    }
    return false;
}
int solve()
{
    memset(match,-1,sizeof(match));
    int cnt = 0;
    for(int u=1;u<=n;++u)
    {
        memset(vis,false,sizeof(vis));
        if(Hungary(u))
            ++cnt;
    }
    return cnt;
}
int main()
{
    while(cin>>n&&n)
    {
        cin>>m;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                cin>>Grape[i][j];
        cout<<solve()<<endl;
    }
}

//鉴定完毕,我是个垃圾

猜你喜欢

转载自www.cnblogs.com/newstartCY/p/11569489.html
今日推荐