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


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

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

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

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

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

  • 相关阅读:
    机试算法学习
    Rockchip平台rk3588源码下载编译(基于Android13)
    【python学习】基础篇-常用函数-匿名函数的使用
    Vue之路由跳转,query传参,子路由,路由模式--hash&history,VueRouter router route三者区别区别
    通讯协议学习之路:RS485协议理论
    技术分享 | 客户分类管理模型在行业中的实践
    软件测试周刊(第87期):天下就没有偶然,那不过是化了妆的、戴了面具的必然。
    重磅!由Linux面试出发,看清华大佬教你如何企业级运维实战
    递归算法 -- 解决全排列问题
    原型原型链面试题
  • 原文地址:https://blog.csdn.net/AC__dream/article/details/125621448