二分图匹配与匈牙利算法

匹配,指一个边集,且其中所有边没有公共顶点。

匈牙利算法能求出二分图上的最大匹配。

之前看大部分讲解里面都说到了增广路,不过有一篇博客在没有说增广路的情况下讲清楚了匈牙利算法

大概是个这样的思路:

    假设顶点集是a,b,每次从a上面选择一个元素ai,往b上面找匹配。如果直接找到了一个和ai有边且没匹配过的bj,那么ai,bj匹配,开始ai+1的操作

   如果在找匹配的时候,手头上这个元素bj和ai有边,但是已经和另一个元素ak匹配了,那么就递归的对ak再找别的匹配,如果ak实在没法找到别的匹配了,那就换个b的元素。

  这个算法会进行递归实现,所有设一个点集vis[]表示本次寻找匹配的时候已经叨扰过哪些b。当ai想要匹配已经和ak匹配的bj时,为了递归的给ak找匹配的时候让ak知道bj已经有点想要了,把vis[j]置1来达到提供这个信息的效果。介于递归实现的尿性,可能会出现“牵一发而动全身”的效果,一堆a的元素都要换匹配(用增广路的说法就是找到了一条很长的增广路),b内可能会有很多元素被置1。另外,因为这是在给一个元素找匹配的时候进行的,所以每次找完了一个点以后都要把vis置空。

hdu2063为例

题目描述里面是男女配对,所以变量名b指上面的a,gi指上面的b的大小。m指邻接矩阵,g[]用于记录配对情况,used[]指上面的vis

#include <bits/stdc++.h>

using namespace std;
const int maxn=505;
int b,gi,e;
bool used[maxn];
bool m[maxn][maxn];
int g[maxn];
bool found(int x)
{
    for(int i=1;i<=gi;i++)
    {
        if(!used[i]&&m[i][x])
        {
            used[i]=true;
            if(g[i]==0||found(g[i]))
            {
            g[i]=x;
            return true;
            }
        }


    }
    return false;
}
int main()
{
    while(cin>>e,e!=0)
    {cin>>gi>>b;

    memset(m,0,sizeof(m));
    memset(g,0,sizeof(g));
    int c1,c2;
      for(int i=1;i<=e;i++)
      {
          cin>>c1>>c2;
          m[c1][c2]=true;
      }
      int su=0;
      for(int i=1;i<=b;i++)
      {
          memset(used,0,sizeof(used));
          if(found(i))su++;
      }
       cout<<su<<endl;
    }
    return 0;


}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值