匈牙利算法寻找最大匹配
问题背景
给定一个x与y对应的连接图,要求每个xi与yi最多只能匹配一次,求最大的匹配次数
求解思路
(1)将x与y的连接转换成矩阵,可相互连接标记为1,其余为0
y1 | y2 | y3 | y4 | y5 | y6 | y7 | |
x1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 |
x2 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
x3 | 1 | 0 | 0 | 1 | 0 | 0 | 1 |
x4 | 0 | 0 | 1 | 1 | 0 | 1 | 0 |
x5 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
x6 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
(2)最外层循环x1到x6,即第一行到第六行,每一行分别从y1到y7遍历
(3)其中used_b = [0, 0, 0, 0, 0, 0, 0]为某一行中被使用的y1
(4)conection_b = [-1,-1,-1,-1,-1,-1,-1]其中每个元素的取值范围为0-5,代表了y对应的第几行x
(5)从第一行开始,选中了y1,conection_b发生变化[0, -1, -1, -1, -1, -1, -1]
i: 0
find: 0
_index: 0
_used_b: [1, 0, 0, 0, 0, 0, 0]
_conection_b: [-1, -1, -1, -1, -1, -1, -1]
index: 0
conection_b: [0, -1, -1, -1, -1, -1, -1]
count
y1 | y2 | y3 | y4 | y5 | y6 | y7 | |
x1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 |
(6)第二行,选中了y2,conection_b发生变化[0, 1, -1, -1, -1, -1, -1]
i: 1
find: 1
_index: 1
_used_b: [0, 1, 0, 0, 0, 0, 0]
_conection_b: [0, -1, -1, -1, -1, -1, -1]
index: 1
conection_b: [0, 1, -1, -1, -1, -1, -1]
count
y1 | y2 | y3 | y4 | y5 | y6 | y7 | |
x1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 |
x2 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
(7)第三行,选中了y1,由于第一行也选中了y1,因此进入递归
i: 2
find: 2
_index: 0
_used_b: [1, 0, 0, 0, 0, 0, 0]
_conection_b: [0, 1, -1, -1, -1, -1, -1]
find: 0
_index: 1
_used_b: [1, 1, 0, 0, 0, 0, 0]
_conection_b: [0, 1, -1, -1, -1, -1, -1]
find: 1
_index: 4
_used_b: [1, 1, 0, 0, 1, 0, 0]
_conection_b: [0, 1, -1, -1, -1, -1, -1]
index: 4
conection_b: [0, 1, -1, -1, 1, -1, -1]
index: 1
conection_b: [0, 0, -1, -1, 1, -1, -1]
index: 0
conection_b: [2, 0, -1, -1, 1, -1, -1]
count
y1 | y2 | y3 | y4 | y5 | y6 | y7 | |
x1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 |
x2 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
x3 | 1 | 0 | 0 | 1 | 0 | 0 | 1 |
(8)得到冲突行的index为0,因此开始find(0),发现y2也被使用,因此继续递归find(1)
y1 | y2 | y3 | y4 | y5 | y6 | y7 | |
x1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 |
x2 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
x3 | 1 | 0 | 0 | 1 | 0 | 0 | 1 |
(9)最后x2找到了y5,因此递归结束,conection_b: [2, 0, -1, -1, 1, -1, -1]
y1 | y2 | y3 | y4 | y5 | y6 | y7 | |
x1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 |
x2 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
x3 | 1 | 0 | 0 | 1 | 0 | 0 | 1 |
(10)第四行,选中了y3,由于没有冲突,所以conection_b: [2, 0, 3, -1, 1, -1, -1]
i: 3
find: 3
_index: 2
_used_b: [0, 0, 1, 0, 0, 0, 0]
_conection_b: [2, 0, -1, -1, 1, -1, -1]
index: 2
conection_b: [2, 0, 3, -1, 1, -1, -1]
count
y1 | y2 | y3 | y4 | y5 | y6 | y7 | |
x1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 |
x2 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
x3 | 1 | 0 | 0 | 1 | 0 | 0 | 1 |
x4 | 0 | 0 | 1 | 1 | 0 | 1 | 0 |
(11)第五行,选中了y4,由于没有冲突,所以conection_b: [2, 0, 3, 4, 1, -1, -1]
i: 4
find: 4
_index: 3
_used_b: [0, 0, 0, 1, 0, 0, 0]
_conection_b: [2, 0, 3, -1, 1, -1, -1]
index: 3
conection_b: [2, 0, 3, 4, 1, -1, -1]
count
y1 | y2 | y3 | y4 | y5 | y6 | y7 | |
x1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 |
x2 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
x3 | 1 | 0 | 0 | 1 | 0 | 0 | 1 |
x4 | 0 | 0 | 1 | 1 | 0 | 1 | 0 |
x5 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
(12)第六行,选中了y4,由于与第五行发生了冲突,所以进入递归find(4)
y1 | y2 | y3 | y4 | y5 | y6 | y7 | |
x1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 |
x2 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
x3 | 1 | 0 | 0 | 1 | 0 | 0 | 1 |
x4 | 0 | 0 | 1 | 1 | 0 | 1 | 0 |
x5 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
x6 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
i: 5
find: 5
_index: 3
_used_b: [0, 0, 0, 1, 0, 0, 0]
_conection_b: [2, 0, 3, 4, 1, -1, -1]
find: 4
used_b: [0, 0, 0, 1, 0, 0, 0]
conection_b: [2, 0, 3, 4, 1, -1, -1]
5
(13)由于第五行中除了y4,没有其他可选线项,因此 find(4) = 0,conection_b没有被改变,因此:conection_b: [2, 0, 3, 4, 1, -1, -1]
y1 | y2 | y3 | y4 | y5 | y6 | y7 | |
x1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 |
x2 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
x3 | 1 | 0 | 0 | 1 | 0 | 0 | 1 |
x4 | 0 | 0 | 1 | 1 | 0 | 1 | 0 |
x5 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
x6 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
代码
>>>def find(x):
... print("find:", x)
... for index in range(7):
... if matrix[x][index] == 1 and used_b[index] == 0:
... used_b[index] = 1
... print("_index:", index)
... print("_used_b:", str(used_b))
... print("_conection_b:", str(conection_b))
... if conection_b[index] == -1 or find(conection_b[index]) != 0:
... print("index:", index)
... conection_b[index] = x
... print("conection_b:", str(conection_b))
... return 1
... return 0
>>>matrix = [
... [1,1,0,1,0,0,0],
... [0,1,0,0,1,0,0],
... [1,0,0,1,0,0,1],
... [0,0,1,1,0,1,0],
... [0,0,0,1,0,0,0],
... [0,0,0,1,0,0,0]
... ]
>>>conection_b = [-1 for _ in range(7)]
>>>count = 0
>>>for i in range(6):
... used_b = [0 for _ in range(7)]
... print("i:",i)
... if find(i):
... print("count")
... count += 1
>>>print("used_b:", str(used_b))
>>>print("conection_b:", str(conection_b))
>>>print(count)
i: 0
find: 0
_index: 0
_used_b: [1, 0, 0, 0, 0, 0, 0]
_conection_b: [-1, -1, -1, -1, -1, -1, -1]
index: 0
conection_b: [0, -1, -1, -1, -1, -1, -1]
count
i: 1
find: 1
_index: 1
_used_b: [0, 1, 0, 0, 0, 0, 0]
_conection_b: [0, -1, -1, -1, -1, -1, -1]
index: 1
conection_b: [0, 1, -1, -1, -1, -1, -1]
count
i: 2
find: 2
_index: 0
_used_b: [1, 0, 0, 0, 0, 0, 0]
_conection_b: [0, 1, -1, -1, -1, -1, -1]
find: 0
_index: 1
_used_b: [1, 1, 0, 0, 0, 0, 0]
_conection_b: [0, 1, -1, -1, -1, -1, -1]
find: 1
_index: 4
_used_b: [1, 1, 0, 0, 1, 0, 0]
_conection_b: [0, 1, -1, -1, -1, -1, -1]
index: 4
conection_b: [0, 1, -1, -1, 1, -1, -1]
index: 1
conection_b: [0, 0, -1, -1, 1, -1, -1]
index: 0
conection_b: [2, 0, -1, -1, 1, -1, -1]
count
i: 3
find: 3
_index: 2
_used_b: [0, 0, 1, 0, 0, 0, 0]
_conection_b: [2, 0, -1, -1, 1, -1, -1]
index: 2
conection_b: [2, 0, 3, -1, 1, -1, -1]
count
i: 4
find: 4
_index: 3
_used_b: [0, 0, 0, 1, 0, 0, 0]
_conection_b: [2, 0, 3, -1, 1, -1, -1]
index: 3
conection_b: [2, 0, 3, 4, 1, -1, -1]
count
i: 5
find: 5
_index: 3
_used_b: [0, 0, 0, 1, 0, 0, 0]
_conection_b: [2, 0, 3, 4, 1, -1, -1]
find: 4
used_b: [0, 0, 0, 1, 0, 0, 0]
conection_b: [2, 0, 3, 4, 1, -1, -1]
5
总结
匈牙利算法的核心思想为:优先考虑最后一行,如果发生冲突,则寻找冲突行可替代项,如果没有可替代项,丢弃最后一行,如果有可替代项,则使用其替代,如果替代之后发生冲突则进入递归,发现冲突不可解除,则丢弃最后一行,冲突可以解除,则使用该方案。
find递归函数的意义在于回溯上一阶段方案能否找到可替代项,使得整个匹配方案之间两两不发生冲突。
匈牙利算法寻找最大匹配相关推荐
- nyoj239 月老的难题 (匈牙利算法,最大匹配,邻接表)
题目239 题目信息 运行结果 本题排行 讨论区 月老的难题 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 月老准备给n个女孩与n个男孩牵红线,成就一对对美好的姻缘. ...
- hdu 4160 Dolls 匈牙利算法求最大匹配
Dolls Time Limit: 2000 ...
- 【模板】匈牙利算法 二分图最大匹配题模板
[任务] 给定一个二分图,用匈牙利算法求这个二分图的最大匹配数. [说明] 求最大匹配,那么我们希望每一个在左边的点都尽量找到右边的一个点和它匹配. 我们一次枚举左边的点x的所有出边指向的点y, 若y ...
- 浅谈匈牙利算法(二分图最大匹配)
前置知识 一张图是二分图,当且仅当它的点可以被分成两部分,而这张图上的所有边的两个端点,都分属不同的部分.我们称这两个点集,一个叫左部,一个叫右部.左部中的点叫左部点:右部中的点叫右部点. 一张图的一 ...
- POJ-3041 匈牙利算法 二分图最大匹配
踢以 给出多个点的坐标 有一种攻击 可以把一次干掉同一列的 或者干掉同一行的 求最少的攻击次数 肥西 由于问题是问选取最少的行和列干掉所有的陨石 可以把输入的r和c看成r和c之间有一条连边因为要实现干 ...
- 【HDU - 2444】The Accomodation of Students(二分图判断 + 匈牙利算法求最大匹配)
题干: There are a group of students. Some of them may know each other, while others don't. For example ...
- 二分图最大匹配——匈牙利算法
二分图最大匹配 (一).二分图的介绍 1.定义 2.充要条件 (二).二分图的匹配 1.二分图的最大匹配 2.增广路径 3.匈牙利算法 (1).复杂度 (2).算法思路 (3).代码实现 (一).二分 ...
- 二分图匹配--匈牙利算法
文章目录 二分图: 匹配 匈牙利算法 代码: 二分图: 二分图是一个无向图,点集分成子集X和Y,图中每一条边都是一边在X一边在Y 当且仅当无向图G的每一个回路次数都是偶数时(包括0),G就是一个二分图 ...
- 图论二分图问题讲解-染色法和匈牙利算法
二分图 概述: 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两 ...
- 匈牙利算法Hungarian algorithm
匈牙利算法是解决寻找二分图最大匹配的. 匈牙利算法(Hungarian Algorithm)是一种组合优化算法(combinatorial optimization algorithm),换句话说就是 ...
最新文章
- 数据蒋堂 | JOIN提速 - 外键指针化
- Data source rejected establishment of connection, message from server: Too many connections解决办法...
- 技术除了工作,还有什么可以提升的?
- 狄利克雷卷积_一些狄利克雷卷积性质的证明
- 信息系统项目管理师为什么不建议自学
- 基本Socket通信流程
- 如何在工作中更好的学习
- [2019.05.09]Linux 学习笔记(3)
- openwrt安装aliddns使用阿里云ddns
- caj转pdf python_caj2pdf gui程序: 转换 CAJ 为 PDF。佛系转换,成功与否,皆是玄学。...
- 日本房地产泡沫破裂后的平民生活
- Vista下最好用输入法 - 搜狗拼音输入法4.0正式版闪亮登场!
- C/C++在线餐馆预订管理系统
- 哈佛架构 VS 冯·诺依曼架构
- vrchat合并账号
- HyperLPR3车牌识别-Linux/MacOS使用:C/C++库编译
- python学习,共同成长,招集python+odoo共同创业合伙人
- htt的缺点有哪些?这里列举的几点,欢迎留言
- 南方科大计算机学院院长,新闻详情 - 计算机科学与工程系 - 南方科技大学
- 抖音死亡计算机背景音乐,抖音死亡计算器app
热门文章
- android自定义速度仪表盘,自定义View实战:汽车速度仪表盘
- 本地词库翻译php,有道词典词库(您也可以轻松翻译离线的有道词典词库)
- 多渠道门店如何进行会员管理和会员营销
- 15-Mixly模拟输出 | Mixly技巧系列
- 【回波损耗(dB)和电压驻波比(VSWR)之间的关系】
- 冷热分离和直接使用大数据库_【TBase开源版测评】深度测评TBase的shard分片和冷热分离存储特性...
- pspice计算机仿真实验,基于OrCAD_PSpice二阶动态电路的计算机仿真分析
- 2021年下半年软考真题软件设计师真题答案(下午题)
- voms下的反射大师_VOMS虚拟大师
- FAT文件系统解析(一) 引导扇区、FAT表及根目录区分析