匈牙利算法(概念及代码完整版)

首先需要知道什么是二分图

定理:设G=<V,E>为一个简单无向图,G为二部图的充要条件是G中的每一个圈的长度都是偶数

二分图的判定:

染色法:假设DFS初始化点A涂黑色,与它相邻的点就涂白色。如果搜到某一点u的相邻点v已经涂色并且与u同色,就不可能是二分图啦

匹配:给定一个二分图G,在G的一个子图M中,M的边集{E}中的任意两条边都不依附于同一个顶点,则称M是一个匹配

最大匹配:包含边数最多的匹配

完美匹配(完备匹配):所有点都在匹配边上的匹配

最佳匹配:如果G为加权二分图,则权值和最大的完备匹配称为最佳匹配

如下图

 

 匈牙利算法用来求二分图的最大匹配

用到的一些概念

      饱和点:结点u被称为M的饱和点,当且仅当有杆e属于M匹配结点u;否则结点u称为非饱和点

      交替路:从一个未匹配点出发,依次经过非匹配边、匹配边、非匹配边........形成的路径叫交替路

      增广路:从一个未匹配点出发,走交替路,如果途径另一个未匹配点(出发点不算),则这条交替路称为增广路

如下图是一条增广路

 由增广路的定义可以推出下述三个结论

1、P的路径长度必定为奇数,第一条边和最后一条边都不属于M

2、P经过取反操作可以得到一个更大的匹配M’

3、M为G的最大匹配当且仅当不存在相对于M的增广路径

算法步骤

1、初始化M为空

2、找一条增广路经P,通过取反操作获得更大的匹配M’代替M

3、重复2操作直到找不出增广路经为止

时间复杂度 O(V*E)

代码实现

//邻接矩阵存图
bool dfs(int u)
{
     for(int v=1;v<=n;v++)
     {
         if(my_map[u][v]&&!vis[v])//u-v边存在,结点v不在M中
         {
              vis[v]=true;
              if(match[v]==-1||dfs(match[v])) //v是非饱和点,或者v是饱和点,看看match[v]是否能
                                              //腾出来v,让v去匹配点u
              {
                   match[v]=u;
                   return true;
              }
         }
     }
     return false;
}

int main()
{
    int sum=0; //匹配数
    memset(match,-1,sizeof match);
    
    for(int i=1;i<=n;i++)
    {
        memset(vis,0,sizeof vis);
        if(dfs(i)) sum++;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值