二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图
二分图将图分成两个点集,而使用匈牙利算法的前提是问题中存在这样的两个点集。
匈牙利算法:
匈牙利算法(Hungarian method)是由匈牙利数学家Edmonds于1965年提出,因而得名。匈牙利算法是基于Hall定理中充分性证明的思想,它是二部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图最大匹配的算法。
增广路(也称增广轨或交错轨):
若P是图G中一条连通两个未匹配顶点的路径,并且属于M的边和不属于M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M的一条增广路径。
![](https://gss2.bdstatic.com/9fo3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D21/sign=31df5e86f51fbe09185ec4156a60e580/dc54564e9258d109f9cac842d658ccbf6c814d10.jpg)
![](https://gss2.bdstatic.com/9fo3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D21/sign=31df5e86f51fbe09185ec4156a60e580/dc54564e9258d109f9cac842d658ccbf6c814d10.jpg)
![](https://gss3.bdstatic.com/-Po3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D42/sign=6e7ae63b44166d223c77149647239272/8d5494eef01f3a291674b43e9e25bc315d607c85.jpg)
![](https://gss0.bdstatic.com/-4o3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D46/sign=dc1a26ce0bf3d7ca08f63e70f31fe9af/35a85edf8db1cb130d6c5de3da54564e92584b3c.jpg)
![](https://gss1.bdstatic.com/-vo3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D42/sign=b030b43e9e25bc312f5d009a5fdf3036/024f78f0f736afc3e4f45e95b419ebc4b6451241.jpg)
![](https://gss3.bdstatic.com/7Po3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D62/sign=90c9f54b80d6277fed12313a2938b43b/b3b7d0a20cf431addc2722c94c36acaf2fdd984c.jpg)
完美匹配: 如果所有点都在匹配边上,称这个最大匹配是完美匹配。
最小覆盖: 最小覆盖要求用最少的点(X集合或Y集合的都行)让每条边都至少和其中一个点关联。可以证明:最少的点(即覆盖数)=最大匹配数
最小路径覆盖:
用尽量少的不相交简单路径覆盖有向无环图G的所有结点。解决此类问题可以建立一个二分图模型。把所有顶点i拆成两个:X结点集中的i和Y结点集中的i',如果有边i->j,则在二分图中引入边i->j',设二分图最大匹配为m,则结果就是n-m。
最大独立集问题:
在N个点的图G中选出m个点,使这m个点两两之间没有边.求m最大值.
如果图G满足二分图条件,则可以用二分图匹配来做.最大独立集点数 = N - 最大匹配数
二分图最大匹配问题的匈牙利算法:
分图的最大匹配有两种求法,第一种是最大流(我在此假设读者已有网络流的知识);第二种就是我现在要讲的匈牙利算法。这个算法说白了就是最大流的算法,但是它跟据二分图匹配这个问题的特点,把最大流算法做了简化,提高了效率。
最大流算法的核心问题就是找增广路径(augment path)。匈牙利算法也不例外,它的基本模式就是:
1 #define N 202 2 int useif[N]; //记录y中节点是否使用 0表示没有访问过,1为访问过 3 int link[N]; //记录当前与y节点相连的x的节点 4 int mat[N][N]; //记录连接x和y的边,如果i和j之间有边则为1,否则为0 5 int gn,gm; //二分图中x和y中点的数目 6 int can(int t) 7 { 8 int i; 9 for(i=1;i<=gm;i++) 10 { 11 if(useif[i]==0 && mat[t][i]) 12 { 13 useif[i]=1; 14 if(link[i]==-1 || can(link[i])) 15 { 16 link[i]=t; 17 return 1; 18 } 19 } 20 } 21 return 0; 22 } 23 int MaxMatch() 24 { 25 int i,num; 26 num=0; 27 memset(link,0xff,sizeof(link)); 28 for(i=1;i<=gn;i++) 29 { 30 memset(useif,0,sizeof(useif)); 31 if(can(i)) num++; 32 } 33 return num; 34 }