文章目录

  • 二分匹配——Bipartite Graph Matchings[LnJJF]
    • 认识:什么是二分图?
    • 理解:现实模型如何与二分图相互转化?
      • 如何判断能否转化?
      • 能够转化的话,如何转化?
    • 应用:已知一个二分图,求最大匹配数的方法是什么?
      • 匈牙利算法示例解析
      • 匈牙利算法求二分图最大匹配的通用思路
      • 匈牙利算法核心部分代码展示(C++)——通用代码模板
    • 活用:那些题目不是求最大匹配数,但是可以转化为求最大匹配数来做?
      • 1. 最小顶点覆盖数=最大匹配数
        • 什么是最小顶点覆盖?
        • 为什么最小顶点覆盖数=最大匹配数?
        • 有什么现实模型,是问最小顶点覆盖的呢?
      • 2. 最大独立集=顶点数-最小顶点覆盖数=顶点数-最大匹配数
        • 什么是最大独立集?
        • 为什么最大独立集=顶点数-最小顶点覆盖数
        • 有什么现实模型,是问最小顶点覆盖的呢?
      • 3. DAG图的最小不相交路径覆盖=顶点数-最大匹配数
        • 什么是DAG图?
        • 什么是DAG图的最小不相交路径覆盖?
        • 为什么DAG图的最小不相交路径覆盖=顶点数-最大匹配数?
    • 后记
    • 参考

二分匹配——Bipartite Graph Matchings[LnJJF]

**前言:**二分匹配的核心就在于求MAX最大匹配数,但是题目不会很直接地让你求MAX最大匹配数,而又可能让你求MIN,如最小顶点覆盖数,DAG图的最小路径覆盖数;也有可能让你求另一种MAX最大独立集。但是题目不论怎么变化,有关二分图的题目,基本都可以转化为求最大匹配数的问题。抓住这点,非常重要。

认识:什么是二分图?

​ 图论中的一种特殊模型。通俗点讲,左边点集U,右边点集V,U有5个点,V有4个点,U的点只和V的点相连,不内部相连,就可以算是一个二分/二部图了。

图1.典型二分图

理解:现实模型如何与二分图相互转化?

如何判断能否转化?

​ 现实模型必须有三个特点,一是有且仅有两个(或者可以创造)具有根本性差异的主体(有两个点集),二是这两个主体中有不同的状态/样态(点集内部有多个独立点),三是主体中的不同样态内部无关联,但与另一样态内部有关联(点集内部的点不相连,两个点集的点相连)。

​ 例如,我们最典型的婚配模型。婚配模型的问题是这样的,有X个男生,Y个女生,大家都是异性恋,男生与女生之间有许多双向暗恋的关系,一个男生可以与多个女生,一个女生也可以与多个男生有双向暗恋关系。假设双向暗恋的男女都能婚配成功,问最多有能有几对婚配成功?

​ 在婚配模型中,我们可以看到这三个特点。一是差异性主体,男女就是两个差异性主体。二是主体中有不同的样态,如男1,男2,如女1,女2,都是不同的。三是主体中的不同样态内部无关联,但与另一样态内部有关联,即问题中所说的,大家都是异性恋,并且男女之间有许多双向暗恋的关系。三个条件都满足,那么就可以将现实模型向二分图转化。

图2.有向无环图的转化示例

​ 另外有一种DAG图的最小不相交路径覆盖问题,比较特殊,原基础只有一个主体,是通过创造第二个主体来实现双主体,如图2所示,具体创造的方法,会于后文介绍。

能够转化的话,如何转化?

​ 能够转化,问题就很简单了。差异性主体,作为独立的点集,放在两端;同一个主体的不同样态,作为题目中的多个点,放在同一个主体下面,按题目次序排列;最后就是找关系,这个关系要么是能够相互匹配,即彼此之间有题意关联的,进行连接。

应用:已知一个二分图,求最大匹配数的方法是什么?

匈牙利算法示例解析

图3.匈牙利算法示例图

​ 答案是匈牙利算法,匈牙利算法,是一种用增广路径求二分图最大匹配的算法。我们同样还是以婚配问题为例,来讲解这个算法。倘若我们有两男三女,可婚配的关系如图3所示,我们可以比较清楚地判断出,最大匹配的方案,就是简单的“男1配女2”+“男2配女1”。但是,这只是凭我们的感觉,计算机并没有我们的感觉,那该怎么做呢?答案是植入这样一个执行套路。

#mermaid-svg-rM4tcr9aEnA4sL1P {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-rM4tcr9aEnA4sL1P .error-icon{fill:#552222;}#mermaid-svg-rM4tcr9aEnA4sL1P .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rM4tcr9aEnA4sL1P .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-rM4tcr9aEnA4sL1P .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rM4tcr9aEnA4sL1P .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rM4tcr9aEnA4sL1P .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rM4tcr9aEnA4sL1P .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rM4tcr9aEnA4sL1P .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rM4tcr9aEnA4sL1P .marker.cross{stroke:#333333;}#mermaid-svg-rM4tcr9aEnA4sL1P svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rM4tcr9aEnA4sL1P .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rM4tcr9aEnA4sL1P .cluster-label text{fill:#333;}#mermaid-svg-rM4tcr9aEnA4sL1P .cluster-label span{color:#333;}#mermaid-svg-rM4tcr9aEnA4sL1P .label text,#mermaid-svg-rM4tcr9aEnA4sL1P span{fill:#333;color:#333;}#mermaid-svg-rM4tcr9aEnA4sL1P .node rect,#mermaid-svg-rM4tcr9aEnA4sL1P .node circle,#mermaid-svg-rM4tcr9aEnA4sL1P .node ellipse,#mermaid-svg-rM4tcr9aEnA4sL1P .node polygon,#mermaid-svg-rM4tcr9aEnA4sL1P .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rM4tcr9aEnA4sL1P .node .label{text-align:center;}#mermaid-svg-rM4tcr9aEnA4sL1P .node.clickable{cursor:pointer;}#mermaid-svg-rM4tcr9aEnA4sL1P .arrowheadPath{fill:#333333;}#mermaid-svg-rM4tcr9aEnA4sL1P .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rM4tcr9aEnA4sL1P .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rM4tcr9aEnA4sL1P .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-rM4tcr9aEnA4sL1P .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-rM4tcr9aEnA4sL1P .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rM4tcr9aEnA4sL1P .cluster text{fill:#333;}#mermaid-svg-rM4tcr9aEnA4sL1P .cluster span{color:#333;}#mermaid-svg-rM4tcr9aEnA4sL1P div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rM4tcr9aEnA4sL1P :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

从上到下遍历至女1,女1可选,选择女1
男1
女1

图4.男1选中女1

#mermaid-svg-9W1Lw4uykCu9feiY {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-9W1Lw4uykCu9feiY .error-icon{fill:#552222;}#mermaid-svg-9W1Lw4uykCu9feiY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-9W1Lw4uykCu9feiY .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-9W1Lw4uykCu9feiY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-9W1Lw4uykCu9feiY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-9W1Lw4uykCu9feiY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-9W1Lw4uykCu9feiY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-9W1Lw4uykCu9feiY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-9W1Lw4uykCu9feiY .marker.cross{stroke:#333333;}#mermaid-svg-9W1Lw4uykCu9feiY svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-9W1Lw4uykCu9feiY .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-9W1Lw4uykCu9feiY .cluster-label text{fill:#333;}#mermaid-svg-9W1Lw4uykCu9feiY .cluster-label span{color:#333;}#mermaid-svg-9W1Lw4uykCu9feiY .label text,#mermaid-svg-9W1Lw4uykCu9feiY span{fill:#333;color:#333;}#mermaid-svg-9W1Lw4uykCu9feiY .node rect,#mermaid-svg-9W1Lw4uykCu9feiY .node circle,#mermaid-svg-9W1Lw4uykCu9feiY .node ellipse,#mermaid-svg-9W1Lw4uykCu9feiY .node polygon,#mermaid-svg-9W1Lw4uykCu9feiY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-9W1Lw4uykCu9feiY .node .label{text-align:center;}#mermaid-svg-9W1Lw4uykCu9feiY .node.clickable{cursor:pointer;}#mermaid-svg-9W1Lw4uykCu9feiY .arrowheadPath{fill:#333333;}#mermaid-svg-9W1Lw4uykCu9feiY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-9W1Lw4uykCu9feiY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-9W1Lw4uykCu9feiY .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-9W1Lw4uykCu9feiY .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-9W1Lw4uykCu9feiY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-9W1Lw4uykCu9feiY .cluster text{fill:#333;}#mermaid-svg-9W1Lw4uykCu9feiY .cluster span{color:#333;}#mermaid-svg-9W1Lw4uykCu9feiY div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-9W1Lw4uykCu9feiY :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

从上到下遍历至女1,女1不可选,看一看女1的男朋友男1能不能换一个女朋友?
男1
女1
男2

图5.男2希望与女1匹配,看看女1的男朋友有没有其它的选择

#mermaid-svg-dHjH1V14kk4U2GY0 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-dHjH1V14kk4U2GY0 .error-icon{fill:#552222;}#mermaid-svg-dHjH1V14kk4U2GY0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-dHjH1V14kk4U2GY0 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-dHjH1V14kk4U2GY0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-dHjH1V14kk4U2GY0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-dHjH1V14kk4U2GY0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-dHjH1V14kk4U2GY0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-dHjH1V14kk4U2GY0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-dHjH1V14kk4U2GY0 .marker.cross{stroke:#333333;}#mermaid-svg-dHjH1V14kk4U2GY0 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-dHjH1V14kk4U2GY0 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-dHjH1V14kk4U2GY0 .cluster-label text{fill:#333;}#mermaid-svg-dHjH1V14kk4U2GY0 .cluster-label span{color:#333;}#mermaid-svg-dHjH1V14kk4U2GY0 .label text,#mermaid-svg-dHjH1V14kk4U2GY0 span{fill:#333;color:#333;}#mermaid-svg-dHjH1V14kk4U2GY0 .node rect,#mermaid-svg-dHjH1V14kk4U2GY0 .node circle,#mermaid-svg-dHjH1V14kk4U2GY0 .node ellipse,#mermaid-svg-dHjH1V14kk4U2GY0 .node polygon,#mermaid-svg-dHjH1V14kk4U2GY0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-dHjH1V14kk4U2GY0 .node .label{text-align:center;}#mermaid-svg-dHjH1V14kk4U2GY0 .node.clickable{cursor:pointer;}#mermaid-svg-dHjH1V14kk4U2GY0 .arrowheadPath{fill:#333333;}#mermaid-svg-dHjH1V14kk4U2GY0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-dHjH1V14kk4U2GY0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-dHjH1V14kk4U2GY0 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-dHjH1V14kk4U2GY0 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-dHjH1V14kk4U2GY0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-dHjH1V14kk4U2GY0 .cluster text{fill:#333;}#mermaid-svg-dHjH1V14kk4U2GY0 .cluster span{color:#333;}#mermaid-svg-dHjH1V14kk4U2GY0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-dHjH1V14kk4U2GY0 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

男1不再访问女1,遍历至女2,判断,男1可以换女朋友女1为女2
男2与女1匹配成功
男1
女2
男2
女1

图6.男1继续刚才的遍历到女2,可以换为女2,男1男2同时配对成功

匈牙利算法求二分图最大匹配的通用思路

​ 从上面案例的执行套路,我们可以得出一个匈牙利算法对于一切二分图求最大匹配的简单流程图。

#mermaid-svg-yeOKWxngFUkfQA3F {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-yeOKWxngFUkfQA3F .error-icon{fill:#552222;}#mermaid-svg-yeOKWxngFUkfQA3F .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yeOKWxngFUkfQA3F .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-yeOKWxngFUkfQA3F .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yeOKWxngFUkfQA3F .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yeOKWxngFUkfQA3F .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yeOKWxngFUkfQA3F .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yeOKWxngFUkfQA3F .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yeOKWxngFUkfQA3F .marker.cross{stroke:#333333;}#mermaid-svg-yeOKWxngFUkfQA3F svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yeOKWxngFUkfQA3F .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-yeOKWxngFUkfQA3F .cluster-label text{fill:#333;}#mermaid-svg-yeOKWxngFUkfQA3F .cluster-label span{color:#333;}#mermaid-svg-yeOKWxngFUkfQA3F .label text,#mermaid-svg-yeOKWxngFUkfQA3F span{fill:#333;color:#333;}#mermaid-svg-yeOKWxngFUkfQA3F .node rect,#mermaid-svg-yeOKWxngFUkfQA3F .node circle,#mermaid-svg-yeOKWxngFUkfQA3F .node ellipse,#mermaid-svg-yeOKWxngFUkfQA3F .node polygon,#mermaid-svg-yeOKWxngFUkfQA3F .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yeOKWxngFUkfQA3F .node .label{text-align:center;}#mermaid-svg-yeOKWxngFUkfQA3F .node.clickable{cursor:pointer;}#mermaid-svg-yeOKWxngFUkfQA3F .arrowheadPath{fill:#333333;}#mermaid-svg-yeOKWxngFUkfQA3F .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yeOKWxngFUkfQA3F .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yeOKWxngFUkfQA3F .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-yeOKWxngFUkfQA3F .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-yeOKWxngFUkfQA3F .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yeOKWxngFUkfQA3F .cluster text{fill:#333;}#mermaid-svg-yeOKWxngFUkfQA3F .cluster span{color:#333;}#mermaid-svg-yeOKWxngFUkfQA3F div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-yeOKWxngFUkfQA3F :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

匈牙利算法求二分图最大匹配数,算法思路图
选中左1,找右点集匹配对象
找到右点集第一个可匹配对象,进行匹配,匹配成功
选中左2,找右点集第一个可匹配对象,进行匹配
如果左2的第一个可匹配对象,目前没有匹配对象,匹配成功
如果左2的第一个可匹配对象,目前已有匹配对象,回到左2希望匹配的对象,它的当前对象
左2希望匹配的对象,它的当前对象如果能更改对象,左2配对成功
左2希望匹配的对象,它的当前对象不能更改对象.
左2继续找右点集第二三...个可匹配对象,直到匹配成功或失败
选中左3,4,5...,重复左2的操作,直至左边点遍历完毕
匹配成功的次数,即为我们要求的最大匹配数

图7.匈牙利算法求二分图最大匹配数的思路流程图

匈牙利算法核心部分代码展示(C++)——通用代码模板

...
bool dfs(int zuo){//输入左边的点名 for(int you=0;you<youmax;you++){//遍历右边的点 if(!vis[you]&&g[zuo][you]){//如果不是原来的匹配对象,并且可连接 vis[you]=1;//防止判断左点能不能改匹配的时候,又把原先的匹配对象选中,从而进入死循环 if(linker[you]==-1||dfs(linker[you])){//可连接的基础上,右点i没有匹配对象或者右点i的匹配对象可以改匹配对象 linker[you]=zuo;//i和u进行连接 return true;//表示匹配成功 }}}return false;
}
int main(){...int cnt=0;//匹配数初始化为0 memset(linker,-1,sizeof(linker));//初始化右点的匹配对象为-1,代表都没有匹配对象 for(int zuo=0;zuo<zuomax;zuo++){//遍历左点 memset(vis,0,sizeof(vis));//初始化每个左点的访问数组为0 if(dfs(zuo))cnt++;//如果左点连接成功,匹配数加一 }       ...
}

活用:那些题目不是求最大匹配数,但是可以转化为求最大匹配数来做?

开始的时候,我们已经说了,很多时候并非是直接求最大匹配数。我们更多的时候,往往是转化为最大匹配数的思路来求解。接下来,我将给出几个常见的转化类型,并讲解为何可以转化,让我们活用匈牙利算法。

1. 最小顶点覆盖数=最大匹配数

什么是最小顶点覆盖?

​ 在二分图中,选中最少的点,关联所有的边,此时的选中的最少点数,就是二分图的最小顶点覆盖数。

图8.最小顶点覆盖数讲解图

为什么最小顶点覆盖数=最大匹配数?

图9.最小顶点覆盖数讲解图2

​ 在图9中,我们不妨先求一下,这个图中的最大匹配数是多少?利用刚才所说的匈牙利算法,我们会得到最终的匹配结果是”男1配女2“+”男2配女1“+”男4配女3”(匹配结果不唯一,但是匹配数为一,我们在此随机举最大匹配上的一种情况)。最大匹配数为3。我们只需要证明,在3条边的每条边上选择1个顶点,总共选择3个对应的顶点一定会覆盖所有的边,即可证明最大匹配数=最小顶点覆盖数。在3条匹配边每条边上选1个点的时候,有一定的要求:如果这两个点中的某个点,有与非匹配点(即图中的蓝圈圈出的点)有连边的话,则只能选择该点;否则任意选。

​ 根据选择要求,我们选出了男4,女1和女2三个点。我们直接根据图,可以看出它们确实是覆盖了所有的边。这是一个例子。但具体如何证明呢?

​ 证明:我们在最大匹配数为M的情况下,在M条匹配边中,每条边挑选出1个点,挑选原则还是同上,即优先选择有与非匹配点(即途中的蓝圈圈出的点)有连边的点,挑选出M个点。

​ 接下来,我们要证明这M个点,能够覆盖所有的边。

​ 对于所有的边,无非就两种情况,第一种它是匹配边(红色边),另一种它是非匹配边(未标红黑边)。

​ 匹配边已经被覆盖,无需多言。

​ 对于非匹配边,也无非就两种情况,第一种是这条边的两个点,有一个是匹配点(红圈圈出的点),有一个是非匹配点(蓝圈圈出的点),这条边必然被我们构造的点集覆盖;第二种是这条边的两个点,都是非匹配点(蓝圈圈出的点),如果真的存在,也就是说没覆盖到,那么这两个点直接相连,最大匹配数应该还要再增加,而不等于M,这显然是与我们求出的最大匹配数为M是矛盾的。

​ 综上所述,最大匹配数M=最小顶点覆盖数M。

有什么现实模型,是问最小顶点覆盖的呢?

​ 最小顶点覆盖数的本质,就在于**“去点消关联”**。还是以刘老师的题目为例子。

图10.严禁早恋例题图

​ 题目大意:有上图男生集与女生集,两者连接代表可以双发可以发展成恋爱关系,为了防止出现早恋现象,学校要开除几个学生,使得所有人不可能发展成恋爱关系,求最少要开出几名学生。

​ 这道题,本质上问的,就是在这个二分图中,去除最少的点,消除所有的关联,本质上,就是选择最少的点,覆盖所有的边。总结成一句话,最小顶点覆盖数,题目的意思,一定有“去点消关联”的意思,如在这题,去点就是开除学生,消关联就是让所有人不可能发展成恋爱关系,读题读到“去点消关联”,那么最小顶点覆盖就八九不离十了,那么匈牙利算法求最大匹配数也就八九不离十了。

2. 最大独立集=顶点数-最小顶点覆盖数=顶点数-最大匹配数

什么是最大独立集?

​ 我们刚才讲到,最小顶点覆盖数的题目,就是去点消关联。最大独立集,本质上就是在此过程上再进一步。也就是“去点消关联,求剩余”因为去点消关联之后,剩余的不就是没有关联的吗,没有关联的,不就是独立的吗?而最多的独立顶点个数,就被我们称为最大独立集。

为什么最大独立集=顶点数-最小顶点覆盖数

​ 一开始,二分图是有关联的,有边相连。最小顶点覆盖数,就是我们实现所有点独立,最少去除的点数,那么顶点总数减去这些点数,不就是最多的独立点数吗?这个相比于之前的证明,更好理解一些。

有什么现实模型,是问最小顶点覆盖的呢?

​ 回到刚才的图10,我们把问题改成,开除一定量的学生,实现最多的学生不可能发展成恋爱,求最多的学生数,即是求此处的最大独立集。

3. DAG图的最小不相交路径覆盖=顶点数-最大匹配数

什么是DAG图?

​ DAG图,英文名为Directed Acyclic Graph,翻译为“有向无环图”。即图是单向,并且不会形成回路的图。

什么是DAG图的最小不相交路径覆盖?

#mermaid-svg-UnxIAqZxvuR4Bx8Q {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .error-icon{fill:#552222;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .marker.cross{stroke:#333333;}#mermaid-svg-UnxIAqZxvuR4Bx8Q svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .cluster-label text{fill:#333;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .cluster-label span{color:#333;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .label text,#mermaid-svg-UnxIAqZxvuR4Bx8Q span{fill:#333;color:#333;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .node rect,#mermaid-svg-UnxIAqZxvuR4Bx8Q .node circle,#mermaid-svg-UnxIAqZxvuR4Bx8Q .node ellipse,#mermaid-svg-UnxIAqZxvuR4Bx8Q .node polygon,#mermaid-svg-UnxIAqZxvuR4Bx8Q .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .node .label{text-align:center;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .node.clickable{cursor:pointer;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .arrowheadPath{fill:#333333;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .cluster text{fill:#333;}#mermaid-svg-UnxIAqZxvuR4Bx8Q .cluster span{color:#333;}#mermaid-svg-UnxIAqZxvuR4Bx8Q div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-UnxIAqZxvuR4Bx8Q :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

1
3
2
4
5

图11.DAG图的最小不相交路径覆盖示例图

​ DAG图的最小不相交路径覆盖,就是在DAG图中,在路径不相交的前提下,用最少的路径覆盖全图。

​ 例如,在图11中,我们不能选择1→3→4+2→3→5两条路径来覆盖全图,因为它们有一个路径相交点3。

​ 但是,我们可以选择1→3→4+2+5这三条路径来覆盖全图(特殊地,单独的点也可以作为一条路径,不过它的路径长度为0而已)。

​ 路径不相交的前提下,最少的覆盖全图的路径数条数,就是最小不相交路径覆盖。如图11的最小不相交路径覆盖就是3。

​ 我的问题是什么?为什么13之后再23不能算匹配?1和3匹配成功了,2和3就不能再匹配。不支持3脚踏两只船。原本有3个点 1 2 3 1和2连了 变成1条路径 和一个点3 1和3连了 变成2条路径 0个点

为什么DAG图的最小不相交路径覆盖=顶点数-最大匹配数?

图12.图11的初始状态

图13.构建DAG图的起点终点二分图

​ 文章的一开始,我们提到,可以通过自行创建另一个主体的方式,来建立一个DAG图的二分图,从而解决DAG图的最小不相交路径覆盖问题。那么我们就以左点集为起点,右点集为终点,构建一个起点终点二分图。

​ 起点终点二分图中,一个起点只能与一个终点单匹配机制,正是这种最小不相交路径覆盖中,不相交的体现

​ **试想,如果起点1连终点3,起点2能再连终点3,终点3同时与起点1和2匹配,那就不符合单个匹配原则,也就不属于二分图最大匹配问题了。**因此,在这样的二分图中,每匹配成功一对,就相当于是找到一条不相交路径。也就是说,在这个二分图中,最大匹配数,就相当于原先DAG图中,最多不相交的路径条数。

​ 现在进入证明阶段,假设原先我们是n个独立顶点(如图12所示),那么我们最少需要n条不相交路径来覆盖这n个独立顶点。每匹配一条不相交路径,本质上就是将两条路径合成为一条路径,总最少需要路径数减1。那么最开始需要用n条不相交路径覆满全图,在已知最多不相交的路径条数为构建二分图的最大匹配数的情况下,只需再减去最大匹配数,就是最少不相交路径覆盖数了!

后记

​ 第一次写知识点总结,整整一天的非娱乐时间基本都在写了,终于在凌晨0:40肝完啦。累并快乐着,尤其是最后的DAG图想不明白,看了网上许多资料也想不明白,自己加入起点终点构图思路后,再能够解释清楚之后,还是很有成就感的。

​ 蒟蒻自语,写博客好爽…

参考

《2021杭电ACM-LCY算法培训》(安利刘老师的课!)

最小顶点覆盖证明思路来源

二分匹配大总结——Bipartite Graph Matchings[LnJJF]相关推荐

  1. C#,图论与图算法,二分图(Bipartite Graph)最佳二分匹配(Maximum Bipartite Matching)算法与源程序

    二部图中的匹配是一组边的选择方式,使两条边不共享一个端点.最大匹配是最大大小(最大边数)的匹配.在最大匹配中,如果向其添加任何边,则该边不再是匹配.对于给定的二部图,可以有多个最大匹配. 我们为什么在 ...

  2. 【人工智能的数学基础】二分图与二分匹配(Bipartite Matching)

    文章目录 1. 二分图的基本概念 2. 图的匹配 3. 二分匹配与匈牙利算法 Bipartite Matching and Hungarian Algorithm. 1. 二分图的基本概念 设 G = ...

  3. 香港大学提出OneNet:一阶段端到端目标检测网络,无需NMS!无需二分匹配!

    点击上方,选择星标或置顶,不定期资源大放送! 阅读大概需要15分钟 Follow小博主,每天更新前沿干货 本文作者:孙培泽 |  编辑:Amusi https://zhuanlan.zhihu.com ...

  4. Bipartite Graph Based Multi-View Clustering

    Bipartite Graph Based Multi-View Clustering 基于二部图的多视图聚类 abstract 对于基于图的多视图聚类,一个关键问题是通过两阶段学习方案捕获共识聚类结 ...

  5. LibreOJ #2006. 「SCOI2015」小凸玩矩阵 二分答案+二分匹配

    #2006. 「SCOI2015」小凸玩矩阵 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 小 ...

  6. UVA - 12083 Guardian of Decency (二分匹配)

    题意:有N个人,已知身高.性别.音乐.运动.要求选出尽可能多的人,使这些人两两之间至少满足下列四个条件之一. 1.身高差>40  2.性别相同  3.音乐不同  4.运动相同 分析: 1.很显然 ...

  7. 石油采集(求联通区域) 2018多校寒假集训 (dfs+二分匹配)

    题目: 链接:https://www.nowcoder.com/acm/contest/76/A 来源:牛客网 随着海上运输石油泄漏的问题,一个新的有利可图的行业正在诞生,那就是撇油行业.如今,在墨西 ...

  8. 二分匹配和一般图匹配

    目录 二分匹配 匈牙利算法 练习 1 2 最小覆盖 练习 1 2 二分图一般独立集 一般图 一般图的最大独立集. 一般图匹配 带花树 增广路 联系 BFS神力 奇环 偶环 LCA 代码 二分匹配 匈牙 ...

  9. SGU 286 Ancient decoration(Euler路径+二分匹配)

    http://acm.sgu.ru/problem.php?contest=0&problem=286 先找欧拉回路,再做二分匹配,输出匹配 有一道题和这个很像:HDU 3551 Hard P ...

最新文章

  1. 初学者怎样看懂python代码_入门编程(初学者怎样看懂代码)
  2. linux 安装 交换分区大小,给已安装的Linux新增Swap交换分区
  3. 如何在C#中使用反射获取集合元素类型
  4. AX2009 的EP开发要点
  5. 【渝粤教育】国家开放大学2018年秋季 0455-22T物流实务 参考试题
  6. 三种方法在地图上绘制网络图
  7. 判断端口是否能用_MSP430单片机的端口解析
  8. 简书 echarts mysql_echarts入门教程
  9. 蚁群算法详解(含例程)
  10. Linux基础入门到精通之虚拟机中安装Linux系
  11. 云服务器转租赁协议,云服务器转租赁协议
  12. LR-Web服务器和应用程序服务器区别(性能指标)
  13. 赵小楼《天道》《遥远的救世主》深度解析(109)天下乌鸦一般黑,不要幻想
  14. 实习之路0--设计模式之策略模式的理解(鸭子类例子)
  15. APT样本分析 -plugx家族RAT⽊⻢
  16. 计算机辅助的临床会谈,天智航参加第十九届国际计算机辅助骨科学术大会
  17. Preference的用法
  18. 金蝉机器人_《金蝉脱壳2》残暴!机器人身份姓名首次曝光监狱更具压迫感
  19. 求一个数除 1 和自身以外的因子
  20. 学习C语言有什么书适合新手看

热门文章

  1. python 正则匹配 条件太多怎么办_Python中正则表达式的巧妙使用
  2. 一个三流学校程序员的奋斗史
  3. 【算法】重复的DNA序列
  4. python(自带的idle+pycharm)常用的快捷键+如何自定义快捷键以及如何修改pycharm的背景颜色
  5. C# 阿里云服务器的对象云存储OSS的上传下载删除-给OSS做个可是化界面
  6. 普洱茶正确冲泡方法的步骤,这3大关键点都不能马虎
  7. R语言笔记⑥——网络爬虫
  8. 推荐几款吾爱上的优秀原创软件~
  9. 学习Docker,有这一篇就够啦!
  10. 7-22 用天平找小球 (10 分)