匈牙利算法

作用:用于求一个二分图中的最大匹配数。

算法:一种类似手动模拟的一种暴力算法。

说明:柯尼希定理:一个二分图的最大匹配数等于这个图中最小点覆盖数,最小点覆盖数(一条边上有一点覆盖即为该边覆盖,求覆盖所有边的最小点数)。柯尼希定理的推论:最小路径覆盖=节点数-最大匹配数(最小路径覆盖—选择最少不相交的边覆盖所有的点)只使用有向无环图。

代码

#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;

const int MaxN=510;

int graph[MaxN][MaxN],flag[MaxN],nxt[MaxN];
//graph为矩阵存图
//flag标记M集合中的元素是否已有匹配点
//nxt用于储存M中的元素匹配了N中的哪个点,next好像是关键字,所以写为nxt
int N,M;

bool Find(int x)//判断找点函数
{
    for(int i=1;i<=M;++i)
    {
        if(graph[x][i]&&!flag[i])//判断两点间是否有边寄目标点是否已有匹配
        {
            flag[i]=1;
            if(nxt[i]==0||Find(nxt[i]))//此处递归,设计巧妙,只有在找到可行解之后再进行一下的重复赋值
            {
                nxt[i]=x;//储存匹配点
                return true;
            }
        }
    }
    return false;
}

int match()//匹配函数
{
    int sum=0;
    for(int i=1;i<=N;++i)
    {
        memset(flag,0,sizeof(flag));//新的一轮新的匹配,标记M集合中的元素是否已有匹配点
        if(Find(i))//判断点i是否可以匹配上
            ++sum;
    }
    return sum;
}

int main()
{
    memset(graph,0,sizeof(graph));//初始化
    memset(nxt,0,sizeof(nxt));
    int T,u,v;
    scanf("%d%d%d",&T,&N,&M);
    while(T--)
    {
        scanf("%d%d",&u,&v);//存边
        graph[u][v]=1;
    }
    int ans=match();
    printf("%d\n",ans);
    return 0;


}

猜你喜欢

转载自www.cnblogs.com/l1l1/p/8986968.html