二分图又称作二部图,是图论中的一种。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图
二分图将图分成两个点集,而使用匈牙利算法的前提是问题中存在这样的两个点集。
匈牙利算法:
匈牙利算法(Hungarian method)是由匈牙利数学家Edmonds于1965年提出,因而得名。匈牙利算法是基于中充分性证明的思想,它是二部图最常见的算法,该算法的核心就是寻找径,它是一种用增广路径求二分图最大匹配的算法。
增广路(也称增广轨或交错轨):
若P是图G中一条连通两个未匹配顶点的路径,并且属于M的边和不属于M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M的一条增广路径。
由 增广路的定义可以推出下述 三个结论:
(1)P的路径个数必定为奇数,第一条边和最后一条边都不属于M。
(2)将M和P进行取反操作可以得到一个更大的匹配 。
(3)M为G的最大匹配当且仅当不存在M的增广路径。
算法轮廓:
(1)置M为空。
(2)找出一条增广路径P,通过异或操作获得更大的匹配 代替M。
(3)重复(2)操作直到找不出 增广路径为止。
复杂度:
时间复杂度邻接矩阵:最坏为 邻接表:
空间复杂度 邻接矩阵:邻接表:
完美匹配: 如果所有点都在匹配边上,称这个最大匹配是完美匹配。
最小覆盖: 最小覆盖要求用最少的点(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 }