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

DETR-二分图匹配 & 匈牙利算法 DETR模型实现的创新点之一就是基于集合的目标函数,那么具体来说这个目标函数是如何设计的呢?二分图匹配、匈牙利算法、一对一匹配都是什么意思? 阅读详情
AI摘要

本文介绍了二分图的概念及二分图匹配的基本原理,详细解释了匈牙利算法求解二分图最大匹配的过程,并提供了算法实现代码及经典例题。

二分图

简单来说,如果图中点可以被分为两组,并且使得所有边都跨越组的边界,则这就是一个二分图。
也就是说,把一个图的顶点划分为两个不相交集 XXX 和 YYY ,使得每一条边都分别连接XXX 、YYY 中的顶点。如果存在这样的划分,则此图为一个二分图。

二分图的一个等价定义是:不含有「奇数条边的环」的图。

这里写图片描述

图111不含有「奇数条边的环」我们习惯上将其画成下列形式:

这里写图片描述

可以看到图222中每条边的两个端点属于不同的集合,这样的图就是一个二分图。
(并且我们人为约定,左边的点属于XXX集合,右边的点属于YYY集合)

匹配:在图论中,一个「匹配」(matching)是一个边的集合,其中任意两条边都没有公共顶点。

例如,图 333、图 444 中红色的边就是图 222 的匹配。

这里写图片描述这里写图片描述

二分图的匹配

我们定义匹配点、匹配边、未匹配点、非匹配边,它们的含义非常显然。例如图 333 中 1、4、5、71、4、5、71、4、5、7 为匹配点,其他顶点为未匹配点。1−5、4−71-5、4-71−5、4−7为匹配边,其他边为非匹配边。

  1. 最大匹配:一个图所有匹配中,所含匹配边数最多的匹配,称为这个图的最大匹配。图 4 是一个最大匹配,它包含 4 条匹配边。
  2. 完美匹配:如果一个图的某个匹配中,所有的顶点都是匹配点,那么它就是一个完美匹配。
    图图图 4 是一个完美匹配。显然,完美匹配一定是最大匹配(完美匹配的任何一个点都已经匹配,添加一条新的匹配边一定会与已有的匹配边冲突)。但并非每个图都存在完美匹配。

这两个概念应该十分明确,举例来说:如下图所示,如果在某一对男孩和女孩之间存在相连的边,就意味着他们彼此喜欢。
是否可能让所有男孩和女孩两两配对,使得每对儿都互相喜欢呢?图论中,这就是完美匹配问题。
如果换一个说法:最多有多少互相喜欢的男孩/女孩可以配对儿?这就是最大匹配问题。
这里写图片描述

匈牙利算法

二分图的最大匹配可以转换为一个网络流的问题,但是我们一般使用匈牙利算法,这种算法更易于理解,方便编写。
介绍这个算法之前,首先要介绍一些必要的概念。

  1. 交错路 : 从一个未匹配点出发,依次遍历未匹配边、匹配边、未匹配边,这样交替下去,这条路径称为交错路。

  2. 增广路 : 从一个未匹配点出发,依次遍历未匹配边、匹配边、未匹配边,这样交替下去,如果最后一个点是未匹配点,这条路径称为增广路。换句话说,起点和终点都为未匹配点的交错路为增广路(特别提醒,这里的增广路和网络流中的增广路的意义不同)

这里写图片描述这里写图片描述

如图所示,图666是图555的其中一条增广路,可以看出由未匹配点999出发,依次沿着边edge(9,4)−>edge(4,8)−>edge(8,1)−>edge(1,6)−>edge(6,1)edge(9,4)->edge(4,8)->edge(8,1)->edge(1,6)->edge(6,1)edge(9,4)−>edge(4,8)−>edge(8,1)−>edge(1,6)−>edge(6,1)到达未匹配点111,显然,这是一条增广路。

观察图666我们可发现增广路的一些特点。

  1. 增广路一定有奇数条边。

  2. 增广路中未匹配边一定比匹配边多一条(因为是从未匹配点出发走交错路到未匹配点结束)

这里其实就表明了研究增广路的意义。
如果找到了一条增广路,那么将未匹配点与匹配边的身份调换,那么匹配的边数就多了一条,这样直到找不到增广路为止,那么整个图的匹配的边数一定最大,也就是找到了二分图的最大匹配。

这里的身份调换是指 :
原来匹配的边为edge(1,6),edge(4,8)edge(1,6),edge(4,8)edge(1,6),edge(4,8),匹配边数为222。找到一条增广路(这里不一定从999开始找,任何一个未匹配点都可以)后,现在匹配的边为edge(2,6),edge(1,8),edge(4,9)edge(2,6),edge(1,8),edge(4,9)edge(2,6),edge(1,8),edge(4,9),匹配边数为333。

匈牙利算法正是利用了增广路的这个性质,从XXX集合中找到一个未匹配点,寻找增广路,找到了匹配数+1,如果没有找到,那么从XXX中找到下一个未匹配的点,再次寻找增广路…重复上述过程,直到XXX集合中的所有节点都被“增广”完毕,无论如何都找不到增广路,那么整个图的匹配数就最大了。

下面给出匈牙利算法的伪代码 :

void hungary()//匈牙利算法
{
    for i->1 to nx//对于集合X中的每一个节点
        if (从未匹配点i出发有增广路)
            匹配数++;
    输出 匹配数;
}
bool findpath(x)//寻找从x出发的对应项出的可增广路
{
    //crossPath[x] = true;这条语句可能会有很多人加上,但是实际上crossPtah总是记录集合Y中的节点是否在交错路上
    for each edge(x,y) in G.E
    {
        if(y is not in crossPath)
        {
            add y into crossPath
            lastX = match[y];//lastX是X集合的上一个与y匹配的节点
            if(y is not matched or findpath(lastX))//如果y已经被了,那么试试从lastX能不能另外找到一条增广路,把当前增广路让给现在的x
            {
                match[y] = x;
                //match[x] = y,wrong !
                return true;//从x出发有增广路
            }
        }
    }
    return false;//从x出发没有增广路
}

时间复杂度 : 对于每一个属于集合X的节点x,调用findpath(x)findpath(x)findpath(x),最坏情况下findpath(x)findpath(x)findpath(x)会遍历所有的边,所以该事件复杂度为 O(V*E)。

推荐两个模板题目 :

hdu 2063
poj 1469

并且给出hdu 2063当做模板 :

#include <cstring>
#include <cstdio>
#pragma comment(linker,"/STACK:1024000000,1024000000")
const int maxn = 505;
const int maxm = 1005;
/*使用G++交题*/
struct Edge
{
    int to,next;
};
Edge edge[maxn];
int head[maxn],tot;
int match[maxn],ans;//match[x] = y表示x的匹配是y
bool inCrossPath[maxn];//在交错路中
int k,m,n;

void Init()
{
    memset(match,-1,sizeof(match));
    memset(head,-1,sizeof(head));
    tot = 0;
    ans = 0;
}
void addEdge(int u,int v)
{
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}
bool findpath(int u)
{
    int v;

    for(int i = head[u] ; i != -1 ; i = edge[i].next){
        v = edge[i].to;
        if(inCrossPath[v] == false){
            inCrossPath[v] = true;
            if(match[v] == -1 || findpath(match[v])){
                match[v] = u;
                return true;
            }
        }
    }
    return false;//千万别忘了这句
}
void Hungary()
{
    for(int i = 1 ; i <= m ; ++i){//只有女生有选择的权利,女生相当于X集合
        memset(inCrossPath,false,sizeof(inCrossPath));//每次清空交错路径
        if(findpath(i))
            ans++;
    }
}
int main()
{
    int u,v;
    while(scanf("%d",&k) != EOF && k){
        Init();
        scanf("%d%d",&m,&n);
        for(int i = 1 ; i <= k ; ++i){
            scanf("%d%d",&u,&v);
            addEdge(u,v);
        }
        Hungary();
        printf("%d\n",ans);
    }
    return 0;
}

推荐几个经典的例题,做完之后差不多就入门了 :

poj 1274 (基础)
poj 2446 (建图特殊)
hdu 1281 (建图特殊)
hdu 2819 (难)

二分图最大匹配的扩展

  1. 最大独立集 : 二分图中最大的一个点集,该点集内的点互不相连(没有边相连)。回想一下图444 : 这里写图片描述显然这里给出了图的一个最大匹配,将最大匹配中的点从原来的节点集合VVV中删除,那么剩下的点不会有任何边相连,也就是说最大独立集数目=∣V∣−最大匹配数最大独立集数目 = |V| - 最大匹配数最大独立集数目=∣V∣−最大匹配数

  2. 最小顶点覆盖 :二分图中,用最少的点,让所有的边至少和一个点有关联。很显然,最大匹配中的结点满足该性质,也就是说最小顶点覆盖数=最大匹配数最小顶点覆盖数 = 最大匹配数最小顶点覆盖数=最大匹配数

  3. 最小路径覆盖:在有向图中找一些路径,这些路径覆盖图中所有的顶点,每个顶点都只与一条路径相关联。在所有的路径覆盖中,路径个数最小的就是最小路径覆盖。最小路径覆盖=最大独立集=∣V∣−最大匹配最小路径覆盖 = 最大独立集 = |V| - 最大匹配最小路径覆盖=最大独立集=∣V∣−最大匹配

以上三条的正确性都不予证明…证明也会是很数学的东西,当做结论记起来就好。

练习题目 :

poj 2060
poj 3041
poj 2226

本文图片摘自http://www.renfei.org/blog/bipartite−matching.htmlhttp://www.renfei.org/blog/bipartite-matching.htmlhttp://www.renfei.org/blog/bipartite−matching.html

匈牙利算法求二分图的最大匹配 二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。 二分图的最大匹配: 匈牙利算法  完美匹配: 如果所有点都在匹配边上,称这个最大匹配是完美匹配。  最小覆盖: 最小覆盖要求用最少 阅读详情

相关推荐

ResNet理论基础与具体实现(详细教程)

论文地址:Deep Residual Learning for Image Recognition ​ Identity Mappings in Deep Residual Networks pytroch源码地址:resnet 0x00 前言 ResNet是2015年就提出的网络结构,中文名字叫作深度残差网络,主要作用是图像分类。现在在图像分割、目标检测等领域都有很...

coordinate的博客 8329

匈牙利算法小结

匈牙利算法 匈牙利算法主要应用于找二分图最大匹配,通过找增广路实现 以下为伪代码 void dfs(int now) { for (遍历当前点可以连的边) { int to=当前能到达的点 if(没访问过to) to打访问标记; if (to没有匹配||to现在的匹配能找到其他节点匹配) 匹配to,now return true; } 找不到,retur...

weiya040214的博客 1703

SUMO仿真教程(5) —— 使用“XML“语言自定义构建路网

文章目录一.简要介绍1.node file2.edge file3.lane definitions(1)路段细分(2)邻近的对向车道(3)删除边或车道4.type file(1)简要概述(2)edge定义中引用type文件的示例(3)指定车辆种类的速度限制5.connections file(1)简要概述:(2)connection的属性参数(3)删除连接(4)设置连接的优先级(5)同一边的多个连接二.演示示例:1.自定义编写node file2.自定义编写edge file3.自定义编写type fil

weixin_50632459的博客 5015

【匈牙利算法】最大二分匹配——算法设计与分析

介绍了最大二分匹配问题,介绍了Hungarian匈牙利算法,并给出算法实例展示。

友人帐_的博客 822

电力现货交易市场-报价方式

电是一种能源,也是一种商品,既然是商品自然可以在市场中进行自由交易。

qq_38225433的博客 5117

5分钟搞定!用FunASR在本地快速部署达摩院Paraformer语音识别模型

本文提供了一份快速部署指南,教你如何在5分钟内利用FunASR工具包在本地电脑上启动达摩院Paraformer语音识别模型。Paraformer作为一款非自回归端到端模型,以其推理速度快、识别精度高的特点,结合FunASR的一键式模型加载和统一API,让开发者能轻松构建本地语音识别系统,极大降低了前沿AI技术的应用门槛。

q9w8e7r6t5的博客 604

匹配算法之 匈牙利算法详解

匹配算法之 匈牙利算法详解

yohnyang的博客 1万+

无人机机场自动化巡检钢铁厂管廊技术方案

摘要:针对钢厂管廊人工巡检效率低、成本高等问题,提出5G+无人机自主巡检解决方案。该系统由智能机库、5G无人机、AI分析平台等组成,可实现自动起降、实时数据传输、缺陷智能识别等功能。无人机配备四合一云台相机,支持42分钟续航和复杂环境飞行,通过深度学习算法自动生成巡检报告。方案实施后可提升巡检效率3倍以上,降低人工成本和安全风险,实现全天候自动化巡检,为钢厂管廊安全管理提供智能化技术支持。(149字)

gxdhlg的专栏 1683

C语言经典算法之匈牙利算法(简要示例)

匈牙利算法主要用于求解赋权二分图的最大权匹配问题。给定一个二分图G=(X,Y,E),其中X和Y分别为两个顶点集,E为边集,并且每条边e=(x,y)有一个非负权重w(x,y)。目标是找到这样的匹配M,使得所有匹配的边的权重之和最大化。

weixin_56154577的博客 1796

智能车图像处理16-进阶篇8--右环岛状态机与补线

这篇文章主要讲述智能车竞赛中如何判断右环岛并且进行状态补线。

taiyuezyh的博客 1万+

华为OD机试真题2025双机位A卷 Python&JavaScript 实现【采购订单】

在一个采购系统中,采购申请(PR)需要经过审批后才能生成采购订单(PO)。每个PR包含商品的单价(假设相同商品的单价一定是一样的)及数量信息。系统要求对商品进行分类处理:单价高于100元的商品需要单独处理,单价低于或等于100元的相同商品可以合并到同一采购订单PO中。针对单价低于100的小额订单,如果量大可以打折购买。

MISAYAONE的博客 1457

【openCV-56】匈牙利算法

匈牙利算法,也被称为匈牙利方法,是一种解决分配问题(Assignment Problem)的算法。分配问题的目标是最小化或最大化一个权重矩阵中的代价或收益,通常涉及将多个任务分配给多个代理,或者将多个物体分配给多个容器等问题。该算法是一个经典的组合优化算法,广泛应用于任务分配、资源分配、匹配问题等领域。匈牙利算法的基本思想是通过数学方法和矩阵操作,寻找一个最优的分配方案,使得整体代价最小或收益最大。它的时间复杂度是O(n^3),其中n是问题规模,即任务数或代理数,适用于中等规模的分配问题。

m0_69378371的博客 1765

无法将“choco”项识别为 cmdlet、函数、脚本文件或可运行程序的名称的解决方案

本文主要介绍了无法将“choco”项识别为 cmdlet、函数、脚本文件或可运行程序的名称的解决方案,希望能对使用wIndows的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 12万+

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

二分图最大匹配(一)、二分图的介绍1、定义2、充要条件(二)、二分图的匹配1、二分图的最大匹配2、增广路径3、匈牙利算法(1)、复杂度 (一)、二分图的介绍 1、定义 二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点 i 和 j 分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。 2、充要条件 无向图G为二分图的充分必要条件是,G至少有两个顶点,且其所有回路的

hahahahahaha5的博客 1万+

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

二分图最大匹配:匈牙利算法的python实现

二分图匹配是很常见的算法问题,一般用匈牙利算法解决二分图最大匹配问题,但是目前网上绝大多数都是C/C++实现版本,没有python版本,于是就用python实现了一下深度优先的匈牙利算法,本文使用的是递归的方式以便于理解,然而迭代的方式会更好,各位可以自行实现。 1、二分图、最大匹配 什么是二分图:二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两...

27Up的博客 3396

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

浅谈用匈牙利算法寻找二分图的最大匹配

本篇博客主要浅析一下利用匈利亚算法求解二分图

qq_46384359的博客 916

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

匈牙利算法简介 → 二分图最大匹配

匈牙利算法冲突处理的逻辑是“后来者居上”、“腾位子”。

hnjzsyjyj的专栏 963

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

1. 二分图的匹配问题1.1 二分图简单来说,如果图中点可以被分为两组,并且使得所有边都跨越组的边界,则这就是一个二分图。 准确地说:把一个图的顶点划分为两个不相交集 U 和 V ,使得每一条边都分别连接U 、 V 中的顶点。如果存在这样的划分,则此图为一个二分图。 二分图的一个等价定义是:不含有「含奇数条边的环」的图。图 1 是一个二分图。为了清晰,我们以后都把它画成图 2 的形式。

jinzhao1993的博客 4880

二分图最大匹配算法:匈牙利、KM

二分图最大匹配:匈牙利算法 二分图最大权匹配:KM算法

Shilong的博客 1527

二分图最大匹配及匈牙利、HK算法

二分图最大匹配 在二分图中,最大匹配是指选出尽可能多的边使得任意两边没有公共端点。 增广路 设MMM为二分图GGG已匹配的边的集合,若PPP是图GGG中一条连接两个未匹配顶点的路径(起点终点分别在两个集合),属于MMM的边和不属于MMM的边交替出现,则PPP称为MMM的一条增广路(直接匹配的边也是特殊的增广路)。 如下图所示,当111和AAA已经匹配,而尝试寻找222的匹配时,发现它只能匹配AAA: 然后尝试让222匹配AAA,这时再给111找新的匹配的过程看做:从222出发,遍历到AAA;再从AAA遍历

Happig的博客 2394

图论——二分图最大匹配与匈牙利算法

匈牙利算法 二分图概念 二分图:简单来说,如果图中点可以被分为两组,并且使得所有边都跨越组的边界,则这就是一个二分图。准确地说:把一个图的顶点划分为两个不相交集UUU和VVV,使得每一条边都分别连接UUU、VVV中的顶点。如果存在这样的划分,则此图为一个二分图。二分图的一个等价定义是:不含有「含奇数条边的环」的图。 判断一个图是不是二分图,我们可以使用BFS搜索算法,从一个顶点开始搜索整个图,层与层直接交替出现,即二分图的左点集和右点集交替出现,该图是二分图的充分必要条件是,BFS搜索中不出现横向边。等价

jiahonghao2002的博客 1042

二分图二•二分图最大匹配之匈牙利算法

题目地址:http://hihocoder.com/problemset/problem/1122?sid=256694 #1122 : 二分图二•二分图最大匹配之匈牙利算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上一回我们已经将所有有问题的相亲情况表剔除了,那么接下来要做的就是安排相亲了。因为

littledouble的专栏 767

二分图的最大匹配、完美匹配和匈牙利算法

这篇文章讲无权二分图(unweighted bipartite graph)的最大匹配(maximum matching)和完美匹配(perfect matching),以及用于求解匹配的匈牙利算法(Hungarian Algorithm);不讲带权二分图的最佳匹配。 二分图:简单来说,如果图中点可以被分为两组,并且使得所有边都跨越组的边界,则这就是一个二分图。准确地说:把一个图的顶点划分为

Tham 在思索中前行! 2947

【算法·命运-39】匈牙利算法二分图最大匹配

匈牙利算法 是一种用于解决 二分图最大匹配 问题的经典算法。它能够在 时间复杂度 O(V \times E) 下找到给定二分图的最大匹配。在一个二分图 G=(U,V,E)G = (U, V, E) 中:最大匹配 是指找到一个边的子集,使得:匈牙利算法是基于 增广路径 的贪心算法,依赖于以下思想:通过找到增广路径,将路径上的匹配边和非匹配边反转(匹配变为非匹配,非匹配变为匹配),从而使匹配数增加 1。 4. 算法分析 时间复杂度: 每次寻找增广路径的复杂度为 O(E),其中 EE 是图中的边数。 最

m0_69378371的博客 1176

匈牙利算法解决二分图最大匹配

前言   匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名。匈牙利算法是基于Hall定理中充分性证明的思想,它是二分图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图最大匹配的算法。 二分图   二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关...

weixin_30828379的博客 299
上一篇: CSAPP学习笔记——Integer Representation
下一篇: 二分图的最佳完美匹配——KM算法
SixDayCoder
博客等级 码龄12年 98粉丝 64原创
评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值