匈牙利算法

  • 一、一些概念
    • 1.二分图
    • 2.二分图的匹配
  • 二、匈牙利算法的实现步骤
    • 1.情况一(你是我的唯一)
    • 2.情况二(你们都是我的翅膀)
    • 3.情况三(我会把你抢过来)
    • 4.情况四(我爱的人已经有了爱人)
  • 三、匈牙利算法的代码实现

一、一些概念

1.二分图

  • 一定不含有奇数环,可能包含长度为偶数的环, 不一定是连通图
  • 二分图是图论中的一种特殊模型。设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。简单来说,如果图中点可以被分为两组,并且使得所有边都跨越组的边界,则这就是一个二分图。准确地说:把一个图的顶点划分为两个不相交子集 ,使得每一条边都分别连接两个集合中的顶点。如果存在这样的划分,则此图为一个二分图,如下图所示的全都是二分图:

关于二分图有一个重要的定理:G为二分图的充要条件是G中的每一个环的长度都是偶数 在这里就不证明了。

2.二分图的匹配

  • 二分图的匹配:给定一个二分图 G,在 G 的一个子图 M 中,M 的边集 {E} 中的任意两条边都不依附于同一个顶点,则称 M 是一个匹配。
  • 二分图的最大匹配:所有匹配中包含边数最多的一组匹配被称为二分图的最大匹配,其边数即为最大匹配数。

理解起来是不是很抽象?没关系,我来举一个例子:让我们假设二分图的左边全为男生,右边全为女生,线连着的男女生为情侣关系,允许出现脚踏n条船等混乱的男女关系的情况,那么:

  • 二分图的匹配:把二分图删除一些边使男女生之间的关系没有出现脚踏n条船的情况,就说删除边后得到的新图为一个匹配(允许出现单身狗的情况)
  • 二分图的最大匹配:删除部分边使得保留的情侣数量最多,我们就称这个匹配为最大匹配。

比如在上面的4张图中,图1就是图3的一个最大匹配。

二、匈牙利算法的实现步骤

在故事的最开始,作为爱神丘比特的你得到了4对男女生之间的关系图

真是混乱的男女关系啊…

不过没关系,我们将化为纯爱战士,来让他们混乱的男女关系恢复正常!开始干活!

1.情况一(你是我的唯一)

首先我们看向男1,发现男1很纯情的只喜欢着女2,那么就成全他们吧。确定他们两个人的情侣关系。

2.情况二(你们都是我的翅膀)

接下来我们看向男2,发现男2喜欢着女1和女3两个女孩子。问问男2吧,他表示:我对这两个女孩子都是真心的,选谁都行!

选谁都行啊,那我们就随便选吧,把男2和女1牵上红线。

3.情况三(我会把你抢过来)

搞定,然后我们再看看男3,男3表示:我也喜欢女1啊!明明是我更加喜欢她!为什么?为什么她和别人在一起了啊!我不能接受!

嗯…看来我们的男3不想放弃啊,那我们尝试和男2交涉一下。

“男2呀,你有备胎吗?”
“有啊,怎么了?”
“男3看上了你女朋友,要不你和你备胎在一起,把你女朋友让给别人吧”
“嗯…好吧,记得让他请我吃饭”(作者对男2这种渣男表示强烈谴责!)

ok,这样的话事情就圆满解决了,可喜可贺可喜可贺。

4.情况四(我爱的人已经有了爱人)

解决了男2和男3的问题,我们再看向男4。

男4说:我喜欢女3!我想和女3在一起!
我看了看,女3不是男2的新女友吗?额…我再去找男2看看吧。

“什么?还要我换?大哥,我没别的备胎了,我拒绝!要是我还有备胎的话还差不多。”(作者对男2这种渣男表示强烈谴责!)

我们只好回头土脸的找到男4。那个,我们交涉失败了,女3是没戏了,要不你换一个追求对象我帮你争取一下?

男4低头沉思了一下,“我觉得吧,女4其实也挺可爱的。”

ok,安排!我们看了看,发现女4还是单身呢,那就成全你们吧。

最后,我们得到的最大匹配就是这样

男女关系正常了,纯爱党一脸满足~

  • 总结:算法描述:
    如果你想找的妹子已经有了男朋友,
    你就去问问她男朋友,
    你有没有备胎,
    有备胎就把你女朋友让给我
    你没有备胎我就只好找我的备胎

多么真实而实用的算法~
时间复杂度为O(nm),但是实际操作中时间一般会小于n*m。
多好的算法啊,连时间复杂度都这么优雅~

三、匈牙利算法的代码实现

例题链接:Acwing 二分图的最大匹配
匈牙利算法板子题,是必须要掌握的题目

给定一个二分图,其中左半部包含 n1 个点(编号 1∼n1),右半部包含 n2 个点(编号 1∼n2),二分图共包含 m 条边。数据保证任意一条边的两个端点都不可能在同一部分中。请你求出二分图的最大匹配数。二分图的匹配:给定一个二分图 G,在 G 的一个子图 M 中,M 的边集 {E} 中的任意两条边都不依附于同一个顶点,则称 M 是一个匹配。二分图的最大匹配:所有匹配中包含边数最多的一组匹配被称为二分图的最大匹配,其边数即为最大匹配数。输入格式
第一行包含三个整数 n1、 n2 和 m。接下来 m 行,每行包含两个整数 u 和 v,表示左半部点集中的点 u 和右半部点集中的点 v 之间存在一条边。输出格式
输出一个整数,表示二分图的最大匹配数。数据范围
1≤n1,n2≤500,
1≤u≤n1,
1≤v≤n2,
1≤m≤1e5
输入样例:
2 2 4
1 1
1 2
2 1
2 2
输出样例:
2

代码实现及分析

//#pragma GCC optimize(2)
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
#include<stack>
#include<set>
#include<bitset>
#include<ctime>
#include<cstring>
#include<list>
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef  pair<int, int> PII;
const int N = 1e6 + 7;
int n1, n2, m;
int h[550], ne[N], e[N], id = 1;// 链式前向星存图
bool st[N];//防止重边的情况导致死循环,防止一个男生重复询问一个女生导致死循环
int match[N];//用来存女生匹配的男生的编号void add(int a, int b)
{e[id] = b, ne[id] = h[a], h[a] = id++;
}int find(int x)  //找男生x能不能匹配到女生
{for (int i = h[x]; i != -1; i = ne[i])  //遍历所有的边{int j = e[i];if (!st[j])  //防止重边导致的死循环{st[j] = true;if (!match[j] || find(match[j]))  //如果这个女生还没有男朋友或者她现在的男朋友有备胎{match[j] = x;  //那就让她男朋友换备胎,然后她成为x的女朋友return true;  //匹配成功}}}return false;  //匹配失败
}void solve()
{mem(h, -1);cin >> n1 >> n2 >> m;while (m--){int a, b;cin >> a >> b;add(a, b);}int res = 0;for (int i = 1; i <= n1; i++){mem(st, false);  //重置if (find(i))  //给i找女朋友啦res++;}cout << res << endl;
}int main()
{std::ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);solve();return 0;
}

作者:Avalon Demerzel,喜欢我的博客就点个赞吧,更多图论与数据结构知识点请见作者专栏《图论与数据结构》

【图论】用匈牙利算法找女朋友(纯爱党的大胜利)相关推荐

  1. 图论 —— 二分图 —— 匈牙利算法

    [基本概念] 1.交替路 从一个未匹配点出发,依次经过 非匹配边.匹配边.非匹配边- 形成的路径 2.增广路 定义:设 M 为二分图 G 已匹配边的集合,若 P 是图 G 中一条连通两个未匹配点的路径 ...

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

    二分图匹配是很常见的算法问题,一般用匈牙利算法解决二分图最大匹配问题,但是目前网上绝大多数都是C/C++实现版本,没有python版本,于是就用python实现了一下深度优先的匈牙利算法,本文使用的是 ...

  3. 二分图匹配及匈牙利算法的全面讲解及python实现

    1.背景 在生活中常常遇到两组元素多对多匹配而又数目有限的情况,我们需要对其进行最大匹配数的分配,使效率最大化.例如,有一组压缩气缸和一组压缩活塞,每一个型号的压缩气缸有一个固定的内径大小,每一个型号 ...

  4. 图论 —— 二分图 —— KM 算法

    [原理] KM 算法是用于求带权二分图的最优匹配的算法,其时间复杂度为 O(N^3). 1.首先选择顶点数较少的为 X 部(左点集),初始时对 X 部的每一个顶点设置顶标,顶标的值为该点关联的最大边的 ...

  5. c语言炉石传说算法设计,FZU Problem 2232 炉石传说(匈牙利算法)

     Problem Description GG学长虽然并不打炉石传说,但是由于题面需要他便学会了打炉石传说.但是传统的炉石传说对于刚入门的GG学长来说有点复杂,所以他决定自己开发一个简化版的炉石传说. ...

  6. 匈牙利算法Hungarian algorithm

    匈牙利算法是解决寻找二分图最大匹配的. 匈牙利算法(Hungarian Algorithm)是一种组合优化算法(combinatorial optimization algorithm),换句话说就是 ...

  7. 匈牙利算法——你一定可以看懂的图论算法

    第一次讲解一个算法,也是最近才学到的一个算法,我的语言表达能力可能不是很强,排版也不是特别好,但是真的有认真在做一篇文章,如果有好的意见可以告诉我,非常感谢. 匈牙利算法是一种在多项式时间内求解任务分 ...

  8. [ACM_图论] The Perfect Stall 完美的牛栏(匈牙利算法、最大二分匹配)

    描述 农夫约翰上个星期刚刚建好了他的新牛棚,他使用了最新的挤奶技术.不幸的是,由于工程问题,每个牛栏都不一样.第一个星期,农夫约翰随便地让奶牛们进入牛栏,但是问题很快地显露出来:每头奶牛都只愿意在她们 ...

  9. 常用代码模板3——搜索与图论(Bellman-Ford算法 、spfa 算法、floyd算法、Kruskal算法、染色法、匈牙利算法 )

    目录 一.树与图的存储 二.树与图的遍历 (1) 深度优先遍历 -- 模板题 AcWing 846. 树的重心 (2) 宽度优先遍历 -- 模板题 AcWing 847. 图中点的层次 拓扑排序 -- ...

  10. 竟该找个我爱的人做我的女朋友或妻子呢?还是该找个爱我的人做我的女朋友或妻子呢?

    石头问:我究竟该找个我爱的人做我的女朋友或妻子呢?还是该找个爱我的人做我的女朋友或妻子呢? 佛笑了笑:这个问题的答案其实就在你自己的心底.这此年来,能让你爱得死去活来,能让你感觉得到生活充实,能让你挺 ...

最新文章

  1. 瞄准VR游戏市场,这款数据手套还提供模块化定制
  2. 洛谷 P1003 铺地毯
  3. λ-矩阵(初等因子)
  4. jenkins 通过自动拉取Gitlab上的代码实现自动更新NGINX
  5. 如何使用 C# 中的 Tuple
  6. Linux基础——操作系统框架
  7. mysql image类型_MyCat教程【mysql主从复制实现】
  8. 【18】Python半成品购物车
  9. 不同表_一个公式搞定数据信息按类别拆分到不同工作表
  10. procedures
  11. 数商云SCM供应链协同管理系统解决方案
  12. 古代益智游戏汉诺塔java解决
  13. 淘宝能承受几百上亿的访问点击,而铁道部的网站为啥分分钟崩溃?
  14. vue中使用google地图(自定义label、信息窗口)
  15. [转]Linux: 结束查看进程命令
  16. matplotlib基础绘图命令之pie
  17. 传统防火墙与下一代防火墙的区别
  18. MFC入门基础(十二)控件 CScrollBar的使用
  19. 设计模式之禅(第2版)
  20. 聚焦 Android 11: Google Play 应用分发与盈利

热门文章

  1. CA证书服务器(6) 利用CA证书配置安全Web站点
  2. Swift2.0新特性
  3. 每天一个linux命令(25):chgrp命令
  4. 爱不意味这“sorry”
  5. 加载本地文件为String类型
  6. Error inflating class android.webkit.WebView Caused by: ...: String resource ID #0x2040003
  7. Springboot监控之二:Spring Boot Admin对Springboot服务进行监控
  8. linux 安装tuxedo
  9. React Native填坑之旅--Button篇
  10. centos mysql