zoukankan      html  css  js  c++  java
  • 图论学习:二分图匹配

    • 更新:

    KM算法正确性的定理:

    转载于:http://www.cnblogs.com/celia01/archive/2012/04/02/2430260.html

    1、二分图中的相关概念:

    定理:无向图G为二分图的充分必要条件是,G至少有两个顶点,且其所有回路的长度均为偶数。

    1.匹配:对于一个给定的图G = (V,E),这幅图的一个匹配M 是图G 的一个子图(由原来的图的一部分顶点和一部分边构成的图),其中每两条边都不相邻(没有公共顶点)。在匹配图中,一个顶点连出的边数至多是一条。如果这个顶点连出一条边,就称这个顶点是已匹配的。匹配可分为极大匹配与最大匹配图G 的一个最大匹配是指边数最多的匹配。最大匹配可能有不止一个,但最大匹配的边数是确定的,并且不可能超过图中顶点数的一半。这是因为一个匹配中的一条边对应一对(两个)顶点,而不同边所对应的两对顶点是完全不同的,否则它们就是相邻的两条边了。

    2.增广路径:指从匹配M 中没有用到的顶点开始,并从M中没有用到的顶点结束的交替路径。
    可以证明,一个匹配是最大匹配,当且仅当它没有任何增广路经(这个结论有时被称为贝吉引理)

    3.最大匹配: 图中包含边数最多的匹配称为图的最大匹配。

    4.完美匹配: 如果所有点都在匹配边上,称这个最大匹配是完美匹配。

    5.最小覆盖: 最小覆盖要求用最少的点(X集合或Y集合的都行)让每条边都至少和其中一个点关联。可以证明:最少的点(即覆盖数)=最大匹配数

    6.最小路径覆盖:用尽量少的不相交简单路径覆盖有向无环图G的所有结点。解决此类问题可以建立一个二分图模型。把所有顶点i拆成两个:X结点集中的i和Y结点集中的i',如果有边i->j,则在二分图中引入边i->j',设二分图最大匹配为m,则结果就是n-m。

    7.最大独立集问题

    在N个点的图G中选出m个点,使这m个点两两之间没有边.求m最大值.

    如果图G满足二分图条件,则可以用二分图匹配来做.最大独立集点数 = N - 最大匹配数

    2、匈牙利算法求解二分图最大匹配

    二分图的最大匹配有两种求法,第一种是最大流(我在此假设读者已有网络流的知识);第二种就是匈牙利算法这个算法说白了就是最大流的算法,但是它跟据二分图匹配这个问题的特点,把最大流算法做了简化,提高了效率。最大流算法的核心问题就是找增广路径(augment path)。匈牙利算法也不例外,它的基本模式就是:

    初始时最大匹配为空
    while 找得到增广路径
    do 把增广路径加入到最大匹配中去

    (注:匈牙利算法虽然根本上是最大流算法,但是它不需要建网络模型,所以图中不再需要源点和汇点,仅仅是一个二分图。每条边也不需要有方向。)
    二分图中的增广路径和网络流中求最大流等一类算法中的增广路径本质上是一致的,但是这里的增广路径就有它一定的特殊性,下面我来分析一下。

    二分图中的增广路径主要有一下特性:

      术语:设G=<V, E>为二分图,M为G的一个匹配。M中边的端点称为M-顶点,其它顶点称为非M-顶点

      图1 图2
    图1是给出的二分图中的一个匹配:[1,5]和[2,6]。图2就是在这个匹配的基础上找到的一条增广路径:3->6->2->5->1->4。我们借由它来描述一下二分图中的增广路径的性质:

    (1)有奇数条边。
    (2)起点在二分图的左半边,终点在右半边。
    (3)路径上的点一定是一个在左半边,一个在右半边,交替出现。(其实二分图的性质就决定了这一点,因为二分图同一边的点之间没有边相连,不要忘记哦。)
    (4)整条路径上没有重复的点。
    (5)起点和终点都是目前还没有配对的点,而其它所有点都是已经配好对的。(如图1、图2所示,[1,5]和[2,6]在图1中是两对已经配好对的点;而起点3和终点4目前还没有与其它点配对。)
    (6)路径上的所有第奇数条边都不在原匹配中,所有第偶数条边都出现在原匹配中。(如图1、图2所示,原有的匹配是[1,5]和[2,6],这两条配匹的边在图2给出的增广路径中分边是第2和第4条边。而增广路径的第1、3、5条边都没有出现在图1给出的匹配中。)
    (7)最后,也是最重要的一条,把增广路径上的所有第奇数条边加入到原匹配中去,并把增广路径中的所有第偶数条边从原匹配中删除(这个操作称为增广路径的取反),则新的匹配数就比原匹配数增加了1个。(如图2所示,新的匹配就是所有蓝色的边,而所有红色的边则从原匹配中删除。则新的匹配数为3。)

    增广路径的长度是奇数,我们设为2k+1条
    又∵第一条是非匹配边 且 匹配边与非匹配边交替出现
    ∴非匹配边有K+1条,匹配边有K条。
    非匹配边比匹配边多了1条。
    此时,我们做取反操作(匹配边变成非匹配边,非匹配边变成匹配边),则匹配边的个数就会在原来的基础上增加1条。
    求最大匹配的“匈牙利算法”就是这样做的。
    无论从哪个匹配开始(整个程序的初始状态是从空匹配开始),每次操作都让匹配数增加1条,不断使它得到扩充,直到找不到增广路径。
    这样就得到了最大匹配了。

    由增广路的定义可以推出下述三个结论:

    1-P的路径长度必定为奇数,第一条边和最后一条边都不属于M。
    2-将M和P进行异或操作(去同存异)可以得到一个更大的匹配M’。
    3-M为G的最大匹配当且仅当不存在M的增广路径。
    不难想通,在最初始时,还没有任何匹配时,图1中的两条灰色的边本身也是增广路径。因此在这张二分图中寻找最大配匹的过程可能如下:
    (1)找到增广路径1->5,把它取反,则匹配数增加到1。
    (2)找到增广路径2->6,把它取反,则匹配数增加到2。
    (3)找到增广路径3->6->2->5->1->4,把它取反,则匹配数增加到3。
    (4)再也找不到增广路径,结束。

    当然,这只是一种可能的流程。也可能有别的找增广路径的顺序,或者找到不同的增广路径,最终的匹配方案也可能不一样。但是最大匹配数一定都是相同的。

    对增广路径,还有一种递归的定义,可能不大准确,但揭示了一种寻找增广路径的一般方法:
    从集合X中的一个非M-顶点A出发,通过与A关联的边到达集合Y中的端点B, 如果B在M中没有任何边匹配,则B就是该增广路径的终点; 如果B已经与C点配对,则这条增广路径就是从A→B→C并加上“从C点出发的增广路径”。 并且这条增广路径中不能有重复的点出现。

    换一张图:
    在这里插入图片描述

    比如我们要从上图中找出一条从X3点出发的增广路径,我们需要做以下几步。

    1.首先从X3出发,它能连接到的点只有点Y3,而Y3已经与X2配对,所以现在的增广路径是X3→Y3→X2在加上从点X2出发的增广路径。

    2.点X2能连接到Y2,Y3,但Y3与前面的路径重复,而{X2, Y2}这条边也不在原来的匹配中,所以只能连接到Y2。所以现在的增广路径是X3→Y3→X2→Y2→X1在加上从点X1出发的增广路径。

    3.点X1能连接到的点且不前面路径重复的点只有Y1。并且Y1在原先的匹配中不与其他所有点配对,属于非M-顶点。因此Y1是该增广路径的终点。所以最终的增广路径是X3→Y3→X2→Y2→X1→Y1。

    严格意义上讲,上面提到的从X2出发的增广路径X2→Y2→X1→Y1和从点X1出发的增广路径X1→Y1并不是真正意义上的增广路径,它们不符合第5个性质。它们的起点是已配对的点。 这里说它们是增广路径只是为了简化搜索过程,它们都只是中间返回值而已。

    现在就进入我们的正题:用匈牙利算法求最大匹配。
    匈牙利算法的基本模式是:

    初始时最大匹配为空 while 找得到增广路径 do 把增广路径加入到最大匹配中去
    比如我们寻找图1的最大匹配,过程可能如下:

    初始最大匹配为空。
    1.找到增广路径X1→Y2,把它取反,则匹配数增大到1,最大匹配变成[X1, Y2]。
    2.找到增广路径X2→Y3,把它取反,则匹配数增大到2,最大匹配变成[X1, Y2],[X2, Y3]。
    3.找到增广路径X3→Y3→X2→Y2→X1→Y1,把它取反,则匹配数增大到3,最大匹配变成[X1, Y1],[X2, Y2],[X3, Y3]。

    4.找不出增广路径,程序结束,得到最大匹配数为3。

    这只是其中一种可能的过程,还有其他不同的过程,得到的增广路径也可能不同,但最后最大匹配数一定是相同的。

    从上面的描述可以看出,搜索增广路径的方法是DFS,写一个递归的函数。当然也可以用BFS。

    至此,理论基础部份讲完了。但是要完成匈牙利算法,还需要一个重要的定理:
    如果从一个点A出发,没有找到增广路径,那么无论再从别的点出发找到多少增广路径来改变现在的匹配,从A出发都永远找不到增广路径。

    有了这个定理,匈牙利算法就成形了。如下:

    初始时最大匹配为空
    for 二分图左半边的每个点i
    do 从点i出发寻找增广路径。如果找到,则把它取反(即增加了总了匹配数)。

    如果二分图的左半边一共有n个点,那么最多找n条增广路径。如果图中共有m条边,那么每找一条增广路径(DFS或BFS)时最多把所有边遍历一遍,所花时间也就是m。所以总的时间大概就是O(n * m)。

    注:

    对于任意图:
    |最小边覆盖|+|最大匹配|=|V|
    二分图的最大匹配=最小点覆盖数
    对于二分图:
    以下数值等价.
    最大匹配
    最小点覆盖
    |V|-最大独立集(二分图or有向无环图)
    |V|-最小边覆盖数
    |V|-最小路径覆盖数(有向无环图)
    |V|-最小路径覆盖数/2(无向图)
    (上面括号里有有向无环图的,均是将一个点拆成两个点连边匹配)
    由于任意图的那几个几乎用不到于是这里只贴二分图的定义

    最小点覆盖(Konig定理):理解为点覆盖边,即用最小的点覆盖所有的边。(若一条边的其中一个端点被选用,这条边就被覆盖了)
    最大独立集:求一个最大的点集,里面的点不存在任何的边相连。
    最小边覆盖:理解为边覆盖点,用最少的边把图中的点全部覆盖。
    最小路径覆盖:用最少的路径把图中的所有点覆盖。

    另外:最大独立集与最小覆盖集互补。

    需要明确的是:
    “图的顶点数目等于顶点覆盖数与最大独立集合的大小之和”对于所有无向图有效
    “最大匹配数=最小顶点覆盖数”只针对二部图有效

    推广到有权的形式也一样,即最大点权独立集与最小点权覆盖集互补
    求最小点权覆盖集可以这样求:
    先对图黑白染色,然后向白色的点放X部,黑色的点放Y部。
    1、连边[S,i],容量等于i的点权。(对于二分图的X集)
    2、连边[i,T],容量等于i的点权。(对于二分图的Y集)
    3、对于有边的i和j连边[i,j](i∈X,j∈Y),容量为INF
    最后得出的最大流就是最小点权覆盖,实际上是最小割与之对应。

    对于有向无环图:
    最大反链=|V|-最大匹配

    你将不再是道具,而是成为人如其名的人
  • 相关阅读:
    C#开源框架
    8 种 NoSQL 数据库系统对比
    安装补丁“此更新不适用于你的计算机”解决办法
    .net开源资料
    winform程序退出
    jquery.chained与jquery.chained.remote使用以及区别
    存储过程使用回滚
    C# Panel中绘图如何出现滚动条
    C#结构体的特点浅析
    如何用堆栈和循环结构代替递归调用--递归转换为非递归的10条军规
  • 原文地址:https://www.cnblogs.com/wsl-lld/p/13393617.html
Copyright © 2011-2022 走看看