二分图匹配

Posted wangguodong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分图匹配相关的知识,希望对你有一定的参考价值。

给定一个二分图G(V,E),V为顶点集,E为边集,在G的一个子图M中,M的边集E中的任意两条边都不依附于同一个顶点,则称M是一个匹配。

极大匹配(Maximal Matching)是指在当前已完成的匹配下,无法再通过增加未完成匹配的边的方式来增加匹配的边数。最大匹配(maximum matching)是所有极大匹配当中边数最大的一个匹配。选择这样的边数最大的子集称为图的最大匹配问题。如果一个匹配中,图中的每个顶点都和图中某条边相关联,则称此匹配为完全匹配,也称作完备匹配。

求二分图最大匹配可以用最大流(Maximal Flow)或者匈牙利算法(Hungarian Algorithm)。

在这里我们主要讲解匈牙利算法。生活中,一个二分图最大匹配的典型应用是男女配对问题。假设有N个男生和M个女生,一个男生可以同时喜欢一个或者多个女生,当然也可以不喜欢任何女生。“喜欢”这种关系可以通过图模型来构建,若男生i和女生j互相喜欢,则在含有N+M个顶点的图中,存在一无向条边i--j。在上述图中,求解通过怎样的配对安排,使得配对的人数最多。

匈牙利算法框架

1. 初始化子图M为空

2. 若找到一个增广路径P,通过取反操作可以获得更多匹配数的子图M‘,M=M‘

3. 重复步骤2直到无法找到一个增广路径

 

何谓增广路径

 技术分享图片

上图红色的三条边(1,2),(3,6),(5,8)为已经匹配的三条边。顶点7为未匹配点,从该点开始,找到一条路径:

7-->6-->3-->2-->1-->4

该路径即为一条增广路径(红色标记的为匹配边,黑色的为未匹配边)。增广路径有如下性质:

  • 非匹配边和匹配边交替出现,其长度必定为奇数,且非匹配边比匹配边多一条
  • 路径的起点和终点都是非匹配点(起点和终点不是同一个点)
  • M为G的最大匹配当且仅当不存在相对于M的增广路径

利用性质“增广路径的非匹配边比匹配边多一条”,然后将非匹配边和匹配边反转,就可以不断增加匹配点和匹配边。上图反转后的结果图如下:

技术分享图片

不断迭代,直到不能找到增广路径,即得到最大匹配(增广路定理)。

bool g[1011][1011];  
bool isVisited[1011]; //标记点i是否被访问过
int matched[1011];  //表示点i匹配到的在另一边的点的编号int n, m; //分别表示左边和右边顶点的个数
bool DFS(int u){
    for(int i = 1; i <= m; i++){
        if(g[u][i] && !isVisited[i]){
            isVisited[i] = true;
            if(!matched[i] || DFS(matched[i])){ //如果点i没有被访问或者从点matched[i]出发可以找到一条在增广路径
                matched[i] = u;//设置匹配的点为u
                return true;
            }
        }
    }
    return false;
}
int maxMatch(){
    int res = 0;
    memset(matched, 0, sizeof matched);
    for(int i = 1; i <= n; i++){
        memset(isVisited, 0, sizeof isVisited);
        if(DFS(i)) res++;
    }
    return res;
}

 个人理解:匈牙利算法在理解上还是很直观的。假设遍历左边的点,对于第i个点,接着逐一访问与点i相连的右边的点,若右边的点为未访问状态,则开始访问。若该点,假设为点s,还未配对,则直接将该点与i配对;若已配对,则查看与s已经配对的点j是否可以改变配对对象而让i与s配对,这就是找增广路径的过程。当点j无法改变配对对象s时,则表示已经达到最大二分匹配。

以上是关于二分图匹配的主要内容,如果未能解决你的问题,请参考以下文章

二分图匹配(模板)

HDU 2236 无题II(二分图匹配+二分)

二分图——匈牙利算法简述

HDU - 1083 Courses(二分图匹配)

匈牙利算法-二分图的最大匹配

洛谷P3386——二分图匹配