匈牙利算法(二分图最大匹配)

距离NOIP2017还有7天,那么我们就准备一些模板来看看吧!
今天复习一下匈牙利算法!
值得一提的是,匈牙利算法求出的二分图最大匹配就是最小点覆盖。这样我们可以做一个“战略游戏”(Luogu P2016)的题目。
模板的具体解释见代码:(Luogu P3386)

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int i,j,k,m,n,e;
int hd[2001],temp;
int mat[2001],b[2001];
int ans; 

struct data
{
    int y,nxt;
}a[2000001];

int r()
{
    int aans=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        aans*=10;
        aans+=ch-'0';
        ch=getchar();
    }
    return aans*f;
}

void add(int xx,int yy)
{
    a[++temp].y=yy;
    a[temp].nxt=hd[xx];
    hd[xx]=temp;
}

bool dfs(int x)
{
    for(int p=hd[x];p;p=a[p].nxt)
    {
        int son=a[p].y;
        if(!b[son])
        {
            b[son]=1;//是否遍历过
            if(!mat[son]||dfs(mat[son]))//如果目标搭档没有搭档或者目标搭档可以被抢走
            {
                mat[son]=x;//那么把让这两个成为一对
                mat[x]=son;
                return 1;//返回当前可行
            }
        }
    }
    return 0;//返回不可行
}

int main()
{
//  freopen("in.txt","r",stdin);
    n=r(),m=r(),e=r();
    int u,v;
    for(i=1;i<=e;i++)
    {
        u=r(),v=r();
        if(v<=m&&u<=n&&u>0&&v>0)//判断数据
        {add(u,v+n);//建双向边
        add(v+n,u);}
    }

    for(i=1;i<=n;i++)
    {
        if(!mat[i])//是否有搭档
        {
            memset(b,0,sizeof(b));
            if(dfs(i))
            ans++;
        }
    }

    cout<<ans;

    return 0;
}
/*
3 4 6
1 1
1 2
1 3
2 2
2 4
3 1
3 3
*/

这里写图片描述

猜你喜欢

转载自blog.csdn.net/Stockholm_Sun/article/details/78437411
今日推荐