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


    二分图的匹配:给定一个二分图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. }

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

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

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

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

  • 相关阅读:
    stl格式-3D三角形
    Vue知识系列(1)每天10个小知识点
    docker搭建mysql环境
    Zabbix技术分享——使用Zabbix6.0监控业务日志
    数据机房智能母线槽技术分析-Susie 周
    2024-04-24 问AI: 在深度学习中,CUDA 是什么?
    【RP-RV1126】烧录固件使用记录
    职场小技巧分享,想要成为受欢迎的人快来
    SpringBoot中个常见的几个问题
    Servlet
  • 原文地址:https://blog.csdn.net/AC__dream/article/details/125621448