二分图匹配

图的匹配概念:

设G=[V,E]一个无向图,M∩E是G的若干条边的集合。如果M中的任意两条边都没有公共的端点,则称M是G的一个匹配。如下图:

                                      

从给定的图G=[V,E]的所有匹配中,把包含边数最多的匹配找出来,这种匹配即所谓的最大匹配问题。若图中的边带权,找一个权和最大的匹配,就是所谓的最佳匹配问题


二分图是一种特殊的图
二分图的节点总是被分成两个互补的部分,这两部分常常用来分别表示两类不同的事物,而两类事物间最基本的关系就是所谓的匹配关系。

无权二分图的最大匹配问题
带权二分图的最佳匹配问题


二分图的概念和判定方法:

设图G=(V,E),若能把V分成两个集合X和Y,使得E中每条边的两个端点,一个在X中,另一个在Y中,则称这样的图为二分图,亦称二部图或偶图。如果二分图G的互补节点子集X中的每一节点都与Y中的所有节点邻接,则称G为完全二分图。显然,二分图最重要的特征是X或Y中的任两个节点都不邻接。
二分图的判定方法:当且仅当无向图G的每一条回路的长度均为偶数时,G才是一个二分图。如果无回路,相当于任一回路的长度为0,0视为偶数。


计算无权二分图的最大匹配:

设M是二分图G中若干条边的集合。如果M中任两条边都没有公共的端点,则称M是G的一个匹配。若M中所含的边数最多,则称M是G的最大匹配;若最大匹配M中的边关联了X端的所有节点,即X中的全部节点和Y中的一个子集中的节点之间确定了一一对应关系,则又称M是G的完备匹配
二分图的最大匹配算法是所有二分图匹配算法的基础。


可增广路径:

计算匹配问题经常需要使用一个可增广路径的概念
设M是二分图的一个匹配,将M中的边所关联的节点称为盖点,其余节点称为未盖点。若一条路径上属于M的边和不属于M的边交替出现,则称该路径为一条交错轨。若路径p是一条起始点和结束点都是未盖点的交错轨,则称p为一条关于M的可增广路经,则M中的匹配边数增加1(为什么?)。显然,图中不存在可增广路径时匹配边数是最多的。这里只考虑二分图的匹配问题。

                                                                            


匈牙利算法基本思路:

计算二分图最大匹配就是应用了可增广路经的概念,每次寻找一条关于M的可增广路径p,通过M←M ⊕ P使得M中的匹配边数增加1。依次类推,直至二分图中不存在关于M的可增广路径为止。此时得到的匹配M就是G的一个最大匹配。

通过DFS算法寻找可增广路径。搜索过程产生的DFS树是一颗交错树,树中任何一条树枝属于M的边和不属于M的边交替出现。取G的一个未盖点作为出发点,它位于DFS树的第0层。设已经构造好了树的第i-1层,现在要构造第i层:当i为奇数时,将那些关联于第i-1层中一个节点且不属于M的边,连同该边关联的另一个节点一起添加到树上;当i为偶数时,则添加那些关联于第i-1层的一个节点且属于M的边,连同该边关联的另一个节点。


在构造DFS树的过程中,若发现一个未盖点v被作为树的奇数层节点,则这棵DFS树上从树根到节点v的路径就是一条关于M的可增广路径P,通过MM ⊕ P 得到图G的一个更大的匹配;如果在构造DFS树的过程中,既没有找到可增广路径,又无法按要求往树上添加新的边和节点,则可以在余下节点中再取一个未盖点作为出发点,构造一棵新的DFS树。这个过程一直进行下去,如果最终仍未得到任何可增广路径,则说明M已经是一个最大匹配了。

                                                                       

                                        增广路径p=t5c1t2c5                                              M<~M ⊕ P


匈牙利算法的流程:

设二分图的邻接表为adj,其中节点i的邻接表为adj[i];X集和Y集的节点数各位n,边数为m;匹配边集为link,其中节点i所在的匹配边为(link[i],i);Y集合中节点的访问标志为used,若Y集合中的节点i已访问,则used[i]=true。
匈牙利算法的核心是判断以X集中的当前节点为起点的可增广路径是否存在。这个判断过程由布尔函数check(u)完成:

伪代码:
Func check(u:integer):boolean;
{for each v∈adj[u] do{
   if not used[v] then{
     used[v]:=true;
     
if(link[v]=0) or(check(link[v]))then
       {link[v]:=u;exit(true);} 

     };
  };
Exit(false);
};

若check(u)函数返回true,则表明u节点被匹配边覆盖。显然,依次对X集的每个节点做依次判断,即可得出二分图的最大匹配,由此,匈牙利算法的主流程为:

伪代码:
main{
  输入二分图信息,构造邻接表adj;
  最大匹配边数初始化为0;
  for i:=1 to n do{
    fillchar(used,sizeof(used),false);
    if check(i) then 最大匹配数+1;
  }
  输出最大匹配数;

时间复杂度分析:寻找一条关于M的可增广路径需要O(E)时间,最多求n条可增广路径,所以总时间为O(nE)。


练习:

Wikioi 2776 寻找代表元
Wikioi 2930 填报志愿
Wikioi 1222 信与信封问题
Wikioi 1022 覆盖
Wikioi 3052 多米诺
Wikioi 1224 糊涂的记者
Wikioi 1027 姓名与ID
Wikioi 2494 Vani和Cl2捉迷藏
Wikioi 2490 导弹防御塔
Wikioi 2294 十九大会议

POJ 2239 Selecting Courses
POJ 1087 A Plug for UNIX
POJ 1274 The Perfect Stall
POJ 2112 Optimal Milking
POJ 1486 Sorting Slides POJ 1466 Girls and Boys
POJ 3692 Kindergarten
POJ 2724 Purifying Machine


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值