匈牙利算法

1. 二分图

二分图: 又称作二部图,是图论中一种特殊模型。设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中每条边所关联的两个顶点 i 和 j 分别属于这两个不同的顶点集(i∈A,j∈Bi \in A,j \in Bi∈A,j∈B),则称图G为一个二分图。

简单来说,如果图中所有顶点可以被分为两个集合,图中所有的边的头和尾不属于同一个顶点集合,而是跨越两个集合,则这个图是一个二分图。

二分图当且仅当图中不含奇数环

  • 如何判断二分图?染色法

    // 判断从某个节点出发,是否所有连通节点都满足相邻节点不同颜色
    bool dfs(std::vector<std::vector<int>> &graph, std::vector<int> &st, int i, int color)
    {// 之前被染色的情况if (st[i]){if (st[i] == color) return true;else return false;  // st[i] != color 矛盾}st[i] = color;for (int j: graph[i]){// 颜色1、2之间的切换可以用3-colorif(!dfs(graph, st, j, 3 - color)) return false;}return true;
    }// 检查邻接表graph是否为二分图
    bool check(std::vector<std::vector<int>> &graph)
    {int n = graph.size();std::vector<int> st(n, 0);     // st: 标记染色,0(未染色),1和2为相邻节点颜色。bool ans = true;for (int i = 0; i < n; i ++){if (!st[i] && !dfs(graph, st, i, 1)){ans = false;break;}}return ans;
    }
    
    import sys
    # 设置递归栈次数
    sys.setrecursionlimit(100000)def dfs(graph, st, i, color):if st[i]:if st[i] == color:return Trueelse:return Falsest[i] = colorfor j in graph[i]:if not dfs(graph, st, j, 3 - color):return Falsereturn Truedef check(graph):n = len(graph)st = [0 for _ in range(n)]ret = Truefor i in range(n):if not st[i] and not dfs(graph, st, i, 1):ret = Falsebreakreturn ret
    

2. 匹配

  • **匹配:**在图论中,一个匹配(matching)是指一个边的集合,其中任意两条边都没有公共顶点。
  • **最大匹配:**一个图所有匹配中,所含匹配边数最多的匹配,称为这个图的最大匹配。
  • **完美匹配:**如果一个图的某个匹配中,所有的顶点都是匹配点,那么它就是一个完美匹配。完美匹配一定是最大匹配,但并非每个图都存在完美匹配。

3. 路径

  • **交替路径:**从一个未匹配点出发,依次经过非匹配边、匹配边、非匹配边…形成的路径称为交替路径。
  • **增广路径:**从一个未匹配点出发,走交替路,如果途径另一个未匹配点(出发的点不算),则这条交替路称为增广路(agumenting path)。
  • 增广路径的性质:
    • P的路径长度必定为奇数,第一条边和最后一条边都不属于M,因为两个端点分属两个集合,且未匹配。
    • P经过取反操作可以得到一个更大的匹配M’。
    • M为G的最大匹配当且仅当不存在相对于M的增广路径。

4. 匈牙利算法

  • **匈牙利算法:**利用增广路径求二分图的最大匹配算法称作匈牙利算法。(匈牙利数学家Edmonds于1965年提出)。
  • **基本思想:**通过寻找增广路径,把增广路径中的匹配边和非匹配边的相互交换,这样就会多出一条匹配边,直到找不到增广路径为止。
// find: 对于集合1的点i,找集合2的匹配对象,成功返回true
// graph: 邻接表
// match: 记录集合2的匹配对象,没有匹配为-1
bool find(std::vector<std::vector<int>> &graph, std::vector<int> &macth, std::vector<bool> &st, int i)
{for (int j: graph[i]){// 已经访问了集合2的对象j,那么跳过if (st[j]) continue;st[j] = true;// j没有被匹配或者j之前的匹配对象macth[j]可以另外被配对if (macth[j] == -1 || find(graph, macth, st, macth[j])){macth[j] = i;return true;}}return false;
}
// hungarian: 求二分图最大匹配,返回最大匹配数量
// graph: 邻接表
// n1: 集合1大小
// n2: 集合2大小
int hungarian(std::vector<std::vector<int>> &graph, int n1, int n2)
{int ans = 0;// match: 记录集合2的匹配对象,没有匹配为-1std::vector<int> macth(n2, -1);for (int i = 0; i < n1; i ++){// st: 记录每次查找是否访问了集合2中的对象std::vector<bool> st(n1, false);if (find(graph, macth, st, i)) ans ++;}return ans;
}
def find(graph, macth, st, i):for j in graph[i]:if st[j]:continuest[j] = Trueif macth[j] == -1 or find(graph, macth, st, macth[j]):macth[j] = ireturn Truereturn Falsedef hungarian(graph, n1, n2):ans = 0match = [-1 for _ in range(n2)]for i in range(n1):st = [False for _ in range(n2)]    if find(graph, match, st, i):ans += 1return ans

5. 算法应用

SORT算法原理(匈牙利匹配+卡尔曼滤波跟踪)

匈牙利算法 求二分图最大匹配相关推荐

  1. 51nod 2006 飞行员配对(二分图最大匹配) 裸匈牙利算法 求二分图最大匹配题

    题目: 题目已经说了是最大二分匹配题, 查了一下最大二分匹配题有两种解法, 匈牙利算法和网络流. 看了一下觉得匈牙利算法更好理解, 然后我照着小红书模板打了一遍就过了. 匈牙利算法:先试着把没用过的左 ...

  2. 算法题 匈牙利算法 求二分图最大匹配(Python)

    题目: 给定一个二分图,其中左半部包含n1n1个点(编号1~n1n1),右半部包含n2n2个点(编号1~n2n2),二分图共包含m条边. 数据保证任意一条边的两个端点都不可能在同一部分中. 请你求出二 ...

  3. 用匈牙利算法求二分图的最大匹配

    转载大神的!! 什么是二分图,什么是二分图的最大匹配,这些定义我就不讲了,网上随便都找得到.二分图的最大匹配有两种求法,第一种是最大流(我在此假设读者已有网络流的知识):第二种就是我现在要讲的匈牙利算 ...

  4. HDU - 2389 Rain on your Parade(Hopcroft-Krap算法求二分图最大匹配)

    题目链接:点击查看 题目大意:给出n个人和m个雨伞,t分钟后就要下雨了,现在给出每个人的坐标和速度,以及雨伞所在的坐标,每个雨伞只能容纳一个人,题目问最多有多少个人能不被淋到 题目分析:二分图最大匹配 ...

  5. 【7.17总结】 匈牙利算法(二分图最大匹配)

    二分图就是把图的点集分成X和Y两个集合且连接每条边的两个顶点分别在两个集合. 匹配是指图的边集的一个子集,其中任意两条边没有相同的顶点. 最大匹配就是找到一个匹配使得匹配里面的边数最多. 增广路径就是 ...

  6. 匈牙利算法求解二分图最大匹配问题

    这是一个非常简单的问题,描述如下,给你两部分的点,问你最大匹配数是多少. 简单描述一下算法流程,首先我们先匹配左边,蓝1先匹配红2:接下来到蓝2,只能匹配红2,但是这这时候发现红2已经有主了,根据匈牙 ...

  7. Hungary(匈牙利算法)——二分图最大匹配

    在复习匈牙利算法的时候,发现这么一篇介绍匈牙利算法的文章,非常通俗易懂,所以就借鉴过来了. 复杂度:邻接矩阵:O(v^3)邻接表:O(V*E) 附上链接:趣写算法系列之--匈牙利算法 下面就附上代码吧 ...

  8. hdu 4160 Dolls 匈牙利算法求最大匹配

    Dolls                                                                               Time Limit: 2000 ...

  9. 匈牙利算法解决二分图匹配问题

    匈牙利算法是由匈牙利数学家Edmonds于1965年提出.匈牙利算法是基于Hall定理中充分性证明的思想,它是二分图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图最大匹配的 ...

最新文章

  1. 修改路由表来使路由分流
  2. c# 学习笔记 (3) 窗体单例模式
  3. 深入剖析C++多态、VPTR指针、虚函数表
  4. JavaScript 几种简单的table切换
  5. 随想录(提高代码质量的几个工具)
  6. 【编程珠玑】第四章 编写正确的程序
  7. windows之Apache服务器搭建
  8. python3携程多任务_python3之携程yield及greenlet
  9. 递归系列——递归树与函数记忆化
  10. PyTorch搭建GoogLeNet模型(在CIFAR10数据集上准确率达到了85%)
  11. 百度文库 复制文本 下载文档
  12. 小黑算法成长日记11:基于Johnson算法de最优流水作业调度
  13. Excel-VBA基础(11):VBA中数组基础知识
  14. 计算机专业就业尴尬问题,计算机专业就业困境初探
  15. java xlsm_poi读取excel(xls和xlsx,xlsm)给定单元格内容
  16. 代码设计时应遵循哪些原则
  17. gcs服务 oracle,gcs resource
  18. Android原生Switch禁止滑动实现
  19. 挣扎中的谷歌“蜻蜓项目”,Google 搜索到底能不能回归大陆?
  20. MyBatis 自关联查询省市区地区数据,一对多自关联查询

热门文章

  1. JiaoZiVideoPlayer 监听播放按钮
  2. CAD编辑指南1:CAD图纸的批量打印和批量修改文字
  3. windows 虚拟机相关功能、组件梳理
  4. 权限管理——RBAC模型总结
  5. 项目部署到服务器上500报错
  6. Email投递简历时应注意的几点重要事项
  7. Linux之mysql安装及初始登录
  8. MD5加密和解密,可作为工具类模块保存
  9. 培训讲师和PPT技巧总结
  10. PointNet论文分析