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


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

    二分图的最大匹配:所有匹配中包含边数最多的一组匹配被称为二分图的最大匹配,其边数和即为最大匹配数。

    匈牙利算法求二分图最大匹配的思想很简单,就是相当于一个一个尝试每一条边,尽可能地增加匹配数,举个例子:

    以这个图为例进行讲解匈牙利算法的思想,我们先让左半部的1号节点进行匹配,按照顺序他会和右半部的1号节点进行匹配,同理左半部的2号节点会和右半部的3号节点进行匹配,左半部的3号节点会和右半部的2号节点进行匹配,轮到左半部的4号节点进行匹配时会发现右半部的2号节点已经与左半部的3号节点匹配成功,所以这个时候就要尝试让左半部的3号节点换一个匹配对象,这个时候左半部的3号节点会选择与右半部的4号节点进行匹配,这个时候右半部的2号节点就空出来了,就可以和左半部的4号节点进行匹配了,所以对应的最大匹配数就是4,这也就是一个逐步尝试的过程,其实正好对应着深搜的过程。

    因为右半部是一个被匹配的过程,所以我们只需要用一个match[i]记录右半部的i号节点所匹配的左半部的节点编号即可,如果match[i]=0说明右半部的i号节点还没有进行匹配。

    思路明白了,代码就比较容易实现,下面给出一道例题:

    题目链接:【模板】二分图最大匹配 - 洛谷

    输入样例:

    1. 4 2 7
    2. 3 1
    3. 1 2
    4. 3 2
    5. 1 1
    6. 4 2
    7. 4 1
    8. 1 1

     输出样例:

    2

    代码:

    1. #include<cstdio>
    2. #include<cstring>
    3. #include<algorithm>
    4. #include<iostream>
    5. #include<queue>
    6. #include<cmath>
    7. using namespace std;
    8. const int N=1e5+10;
    9. int h[N],ne[N],e[N],idx;
    10. int match[N];//match[i]记录与右半部i号节点相匹配的左半部的节点编号
    11. bool vis[N];//vis[i]标记右半部的i号节点有没有被考虑过
    12. void add(int x,int y)
    13. {
    14. e[idx]=y;
    15. ne[idx]=h[x];
    16. h[x]=idx++;
    17. }
    18. bool find(int x)
    19. {
    20. for(int i=h[x];i!=-1;i=ne[i])
    21. {
    22. int j=e[i];
    23. if(vis[j]) continue;
    24. vis[j]=true;
    25. if(match[j]==0||find(match[j]))
    26. {
    27. match[j]=x;
    28. return true;
    29. }
    30. }
    31. return false;
    32. }
    33. int main()
    34. {
    35. int n1,n2,m;
    36. cin>>n1>>n2>>m;
    37. int u,v;
    38. memset(h,-1,sizeof h);
    39. for(int i=1;i<=m;i++)
    40. {
    41. scanf("%d%d",&u,&v);
    42. //因为只需要从左半部向右半部进行匹配,所以只需要加单向边
    43. add(u,v);
    44. }
    45. int ans=0;
    46. for(int i=1;i<=n1;i++)
    47. {
    48. //每个右半部的点都只会被尝试一次,所以每次都需要初始化
    49. memset(vis,false,sizeof vis);
    50. if(find(i)) ans++;
    51. }
    52. cout<<ans;
    53. return 0;
    54. }

    最后再给大家稍微提一下最小点覆盖问题,这个问题也是可以利用匈牙利算法来解决的。

    最小点覆盖问题就是我们想找到最少的一些点,使得二分图中所有的边的两个顶点至少有一个在这些点之中。

    这里就不详细介绍了,直接给大家说出个结论就够用了。

    一个二分图中的最大匹配数等于这个图中的最小点覆盖数。

  • 相关阅读:
    SSM之spring注解式缓存redis->redis整合,redis的注解式开发及应用场景,redis的击穿穿透雪崩
    使用 Python 和机器学习掌握爬虫和情感分析
    GDAL栅格程序通用命令
    SQL server 2008 r2 安装教程
    【CSDN】如何开启CSDN文章下的显示微信公众号、微信号、官方网站、QQ号、QQ群 ?
    Redis
    每日一题|2022-11-23|1742. 盒子中小球的最大数量|Golang
    笔记网站测试报告
    【Odoo】Odoo16-性能优化提升
    Linux开源防病毒引擎ClamAV
  • 原文地址:https://blog.csdn.net/AC__dream/article/details/125621448