zoukankan      html  css  js  c++  java
  • 二分图最大匹配

    二分图是图,可以用图的数据结构存储二分图,邻接矩阵和邻接表

    二分图的特点是,图的顶点可以分为两组,两组组内的节点之间没有连接,所有的连接都是在两组之间的。

    所谓一个匹配是两组节点一对一的连接。

    二分图的最大匹配所要完成的一个任务是在一个二分图中找出最多的匹配数。

    二分图最大匹配匈牙利算法的核心在于新增加的一对匹配能否成功的加入到结果集当中去。

    能够成功加入分为两种情况

    情况1.右侧的节点还没有连接

    情况2.如果右侧的节点已经连接,通过调整右侧节点连接的左节点,将右侧节点空出来。(这是一个递归的过程)

    为什么在为左边的每一个顶点匹配是都要重置数组?

    防止上一轮的遍历对当前造成影响。实际上标记vis数组的过程就是情况2的调整过程。

    每一轮的调整都是独立的。

    代码模板

    hdu2063

    1. /* 
    2. 匈牙利算法解决二分图最大匹配问题 
    3. 采用的邻接矩阵的形式,g[i][j] 
    4. maxn代表一边最多的顶点数,un代表左边顶点数,vn代表右边顶点数 
    5. linked[i]代表右边的第i个点与左边哪个点相匹配 
    6. */  
    7.   
    8. #include <iostream>  
    9. #include <stdio.h>  
    10. #include <algorithm>  
    11. #include <string.h>  
    12. using namespace std;  
    13. const int maxn=502;  
    14. int un,vn;//左边顶点数,右边顶点数  
    15. int g[maxn][maxn];//邻接矩阵来存储边  
    16. int linked[maxn];//右边的点和左边的哪个点匹配  
    17. bool vis[maxn];  
    18.   
    19. bool dfs(int u)  
    20. {  
    21.     for(int v=1;v<=vn;v++)//遍历右边顶点  
    22.     {  
    23.         if(g[u][v]&&!vis[v])  
    24.         {  
    25.             vis[v]=1;  
    26.             if(!linked[v]||dfs(linked[v]))//右边顶点还没有被匹配,或者已经匹配的前面左边顶点可以去寻找另一个匹配而把该右边顶点“腾出空位”让给当前左边顶点u  
    27.             {  
    28.                 linked[v]=u;  
    29.                 return true;  
    30.             }  
    31.         }  
    32.     }  
    33.     return false;  
    34. }  
    35.   
    36. int hungary()  
    37. {  
    38.     int ans=0;  
    39.     memset(linked,0,sizeof(linked));  
    40.     for(int u=1;u<=un;u++)//遍历左边顶点,去寻找与之匹配的右边顶点  
    41.     {  
    42.         memset(vis,0,sizeof(vis)); 
    43.         if(dfs(u))//去找u能不能匹配,如果可以匹配的话,ans++  
    44.             ans++;  
    45.     }  
    46.     return ans;  
    47. }  
    48.   
    49. int k,m,n;//m为题目中要求输入的左边顶点数,n为题目中要求输入的右边顶点数  
    50. int main()  
    51. {  
    52.     while(scanf("%d",&k)!=EOF&&k)  
    53.     {  
    54.         scanf("%d%d",&m,&n);  
    55.         un=m;vn=n;  
    56.         memset(g,0,sizeof(g));  
    57.         int u,v;  
    58.         for(int i=1;i<=k;i++)  
    59.         {  
    60.             scanf("%d%d",&u,&v);//u和v有边  
    61.             g[u][v]=1;  
    62.         }  
    63.         printf("%d ",hungary());  
    64.     }  
    65.     return 0;  
    66. }  
    参考资料

    http://blog.csdn.net/sr_19930829/article/details/41843563

    http://blog.csdn.net/dark_scope/article/details/8880547

    我表示我真是什么都不懂的小白。。下面是以为大神的关于二分图的讲解,非常详细,码一下

    http://blog.csdn.net/sixdaycoder/article/details/47680831

     

  • 相关阅读:
    backgroudWork使用案例
    UAP单据不能设定【分割】符行使权限管理
    此博客所有内容仅供个人学习使用
    十大排序算法——实现程序
    Linux基础(更新ing......
    树莓派基于tensorflow的数字识别
    树莓派系统初始化配置
    树莓派初始配置步骤(无图版)
    PC、虚拟机Ubuntu和开发板实现三者互ping,可挂载nfs传输文件
    Linux目录结构
  • 原文地址:https://www.cnblogs.com/MalcolmMeng/p/8442977.html
Copyright © 2011-2022 走看看