二分图匹配——从入门到入土

基础知识

形式化定义:

二分图:\(G = (L, R, E)\),满足 \(\forall (u, v) \in E\) 都有 \(u \in L, v \in R\)\(u \in R, v \in L\)

可知“图中没有长度为奇数的环”是这个图是二分图的充分必要条件。

图的匹配是一个 \(E_m \subseteq E\) 满足 \(\nexists i \in V(\text{当} G \text{是二分图时} V = L \cup R)\) 满足 \(\exists (u, v), (w, x) \in E_m\)\([u = i] + [v = i] + [w = i] + [x = i] > 1\)

图的极大匹配是一个 \(E_{M} \subseteq E\) 满足 \(\nexists i \in E \ \backslash \ E_M\) 满足 \(E_M \cup i\) 也是一个匹配。

二分图最大匹配

匈牙利算法(KM 算法)

这个算法很简单。

每一次找到二分图上一个 \(u \in L\)\(v \in R\) 并且 \(v\) 没有被匹配的路径,把答案加一。

在找路的过程中搜出来的一棵树叫交错树,树上从 \(u\) 开始的路径叫一条交错路,成功找到的;一条路径叫增广路。

有一种 Dinic 的感觉,但是图没分层 Dinic 假了

单次增广时间复杂度 $O(|V| + |E|)$

很简单。

每次增广的时候最坏会遍历整张图,于是时间复杂度就是 \(O(|V| + |E|)\)

总共会增广 $O(|V|)$ 轮

还是很简单。

每一次找到一条增广路时答案加一,答案是 \(O(|V|)\) 的,所以增广轮数就是 \(O(|V|)\) 的。

把这两个东西乘起来,总共的时间复杂度是 \(O(|V|(|V| + |E|))\) 的。

#include <bits/stdc++.h>
using namespace std;int n, m, k, t[550], a, b, r[550], id[550], ans, vis[550];
vector<int> to[550];int DFS(int x) {if(vis[x]) {return 0;}vis[x] = 1;for(auto i : to[x]) {if(!r[i]) {r[i] = x;t[x] = i;return 1;}if(DFS(r[i])) {r[i] = x;t[x] = i;return 1;}}return 0;
}void KM() {for(int i = 1; i <= n; i++) {fill(vis + 1, vis + n + 1, 0);ans += DFS(i);}
}int main() {for(cin >> n >> m >> k; k--; ) {cin >> a >> b;to[a].push_back(b);}KM();cout << ans << '\n';for(int i = 1; i <= n; i++) {if(t[i]) {cout << i << ' ' << t[i] << '\n';}}return 0;
}

Hopcroft-Karp 算法

Dinic 永远的神

其实跟 KM 算法几乎一模一样,只改了一个地方:每一次只增广最短的增广路。

欸?听起来跟 Dinic 很像?

我们比较一下 Dinic 与 Hopcroft-Karp 的流程 买一送一

Dinic
  1. BFS 出层次图;

  2. DFS 出阻塞流(层次图的最大流);

  3. 把阻塞流合并;

  4. 更新残量网络。

Hopcroft-Karp
  1. BFS 出层次图;

  2. DFS 出这时候的额外匹配;

  3. 合并匹配;

  4. 更新图。

这俩不是一样的吗?

对,对,就是一样的。

所以根据 Dinic 在这种特殊图上的时间复杂度,我们得到——

这个算法的时间复杂度是 \(O(|E| \min(|E|^{\frac{1}{2}}, |V|^{\frac{1}{2}}))\) 的。

稠密图上 \(|E| = O(|V|^2)\),所以是大概 \(O(|V|^3)\) 的;

稀疏图上 \(|E| = O(|V|)\),所以是大概 \(O(|E| |V|^{\frac{1}{2}})\) 的。

只有 \(|V| = 2000, |E| = 4 \times 10^6\) 才能卡掉。

而且Dinic 是“天选之子”时间跑不满......

#include <bits/stdc++.h>
using namespace std;int n, m, k, t[100010], a, b, r[100010], id[100010], ans, vis[100010], dis[100010];
vector<int> to[100010];
queue<int> q;//DFS 出额外匹配
int DFS(int x) {if(vis[x]) {return 0;}vis[x] = 1;for(auto i : to[x]) {//更新图if(!r[i]) {r[i] = x;t[x] = i;return 1;}if(dis[r[i]] == dis[x] + 1 && DFS(r[i])) {r[i] = x;t[x] = i;return 1;}}return 0;
}//BFS 出层次图
int BFS() {fill(vis + 1, vis + n + 1, 0);fill(dis + 1, dis + n + 1, 0);for(int i = 1; i <= n; i++) {if(!t[i]) {q.push(i);dis[i] = 1;}}int f = 0;for(; q.size(); q.pop()) {int tmp = q.front();for(auto i : to[tmp]) {if(!r[i]) {f = 1;}if(r[i]) {if(!dis[r[i]]) {dis[r[i]] = dis[tmp] + 1;q.push(r[i]);}}}}return f;
}void dinic() {for(; BFS(); ) {// 合并匹配for(int i = 1; i <= n; i++) {if((!t[i]) && DFS(i)) {ans++;}}}
}int main() {ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);for(cin >> n >> m >> k; k--; ) {cin >> a >> b;to[a].push_back(b);}cout << ans << '\n';for(int i = 1; i <= n; i++) {if(t[i]) {cout << i << ' ' << t[i] << '\n';}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/738136.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

刘积仁的大健康“长跑”

软件是一个长命的产业,但软件企业的寿命都很短。懂得怕死,才能有机会活得长久。 这一次,刘积仁又为东软医疗找到了强大助力!中国通用技术(集团)控股有限责任公司(以下简称通用技术集团)所属资本公司战略投资东软集团在医疗健康领域资的创新业务公司——东软医疗,双方也由…

【AppStore】一文让你学会IOS应用上架Appstore

咱们国内现在手机分为两类,Android手机与苹果手机,现在用的各类APP,为了手机的使用安全,避免下载到病毒软件,官方都极力推荐使用手机自带的应用商城进行下载,但是国内Android手机品类众多,手机商城各式各样,做不到统一,所以Android的APP上架得一个一个平台去申请上架,…

关于airtest生成的报告中缺少poco语句问题

1、airtest生成的报告只显示airtest的相关操作,如果是poco和airtest-selenium的操作则不记录。因此需要在报告中引用插件。支持poco语句插件,poco.utils.airtest.report 支持airtest-selenium语句插件,airtest_selenium.report2、在IDE运行 .py 脚本报告生成的依据是脚本运行…

xshell7的下载ssh远程连接

1.下载地址家庭/学校免费 - NetSarang Website (xshell.com) 2.下载后一路next,来到主页面,我们来连接一下试一试吧,这里主机就是ifconfig得到的 3.用户名一般都是root密码是自己设置的那个 4.连接的时候注意比如我要连接Node1那么node1就要保持开启并却防火墙已经关闭 5.看一…

xhcms1.0

xhcms1.0 目录结构 admin --管理后台文件夹 css --存放css的文件夹 files --存放页面的文件夹 images --存放图片的文件夹 inc --存放网站配置文件的文件夹 install --网站进行安装的文件夹 seacmseditor --编辑器文件夹 te…

关于巴图自动化Profinet协议转Modbus协议网关模块怎么配置IP地址教学

Profinet协议和Modbus协议是工业通讯常用协议,通过巴图自动化PN转Modbus网关模块(BT-MDPN10)实现连接。常见的协议有:ModbusTCP协议,Profibus协议,Profibus DP协议,EtherCAT协议,EtherNET协议,CAN,CANOPEN等Profinet协议和Modbus协议是工业领域中常用的两种通讯协议,…

基础篇:Stable Diffusion 基础原理详述

【基础篇】Stable Diffusion 基础原理详述前言我认为学习 ComfyUI 应该先从理论学起。与传统绘图工具(如 Photoshop 或 Figma)相比,AI 绘图工具有着显著不同。首先,许多设置和操作在 AI 绘图工具中是非可视化的,这意味着即使你更改了某个配置,界面上也未必会有任何变化,…

微信云开发数据库连接

//.js文件const db = wx.cloud.database()Page({//页面的初始数据data: {dataObj:"" //定义对象dataObj}, //查询数据getData(){db.collection("pro1").where({ //pro1为数据库名author:"张三" …

Camstar里拿到Grid的行数据

两种方法: 1.GridDataMode属性为Geceric的:拿到的数据直接放在datatable里,并且赋值给grid,这里我把拿来的数据放在了一个集合里,测试用的 随便写写 2.GridDataMode属性为ItemList的:这里是用了一个集合去接收datatable的值,再把集合赋值给grid这里和第一种的区别是我没有…

MQTT专题

什么是Mqtt MQTT协议 全称是(Message Queuing Telemetry Transport),即消息队列遥测传输协议。 是一种基于发布/订阅(Publish/Subscribe)模式的轻量级通讯协议,并且该协议构建于TCP/IP协议之上,我们知道TCP协议本身就具有高可靠性的特点,因此基于其上的MQTT协议同样也…

安装visual studio失败,组策略阻止安装webview2

排查安装和升级问题 - Visual Studio | Microsoft Learn 需要修改注册表 ,将 InstallDefault值改为1注册表路径 HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\EdgeUpdate

appium 使用

refer to: python+appium2~inspector工具使用及定位操作元素~_哔哩哔哩_bilibili 1 APPium Inspector 可以查看Android应用的 包名 和activity 打开APP,且处于启动页面 Q1 noReset=True 设置每次APP启动 不重头 初始化环境 怎么实现呢 Q1 那我们现在用的是appium1 还是 appi…

7月11日云技术研讨会 | 车载信息安全全流程实施方案

7月11日,经纬恒润《车载信息安全全流程实施方案》云技术研讨会,与您相聚云端,不见不散! 伴随着汽车的智能网联化发展,网络攻击也逐渐渗透漫延至汽车领域,汽车行业面临着重大的信息安全挑战。此外,UNECE WP.29 R155和ISO/SAE 21434等标准也对汽车的信息安全提出了规…

基于全数字实时仿真的嵌入式DevOps解决方案

​为丰富浙江省信息技术应用创新(以下简称“信创”)产业生态,在全社会各领域形成示范效应,浙江省经信厅联合省密码管理局开展2023年浙江省深化信创典型案例评选工作。经过征集申报、专家评选、名单公示等程序,确定36个应用示范案例和24个典型解决方案。【典型解决方案】 基…

巴图自动化PN转Modbus RTU协议转换网关模块快速配置

巴图自动化推出Profinet转Modbus网关模块BT-MDPN10,实现Modbus和Profinet设备互联互通。配置简便,提高系统智能化和生产效率。工业领域中常用的通讯协议有:Profinet协议,Modbus协议,ModbusTCP协议,Profibus协议,Profibus DP协议,EtherCAT协议,EtherNET协议,CAN,CanO…

springboot+vue前后端分离项目-项目搭建7-服务器上安装部署

1.下载VMware(个人使用版),官网下载,需要先用邮箱注册,下载地址:https://support.broadcom.com/group/ecx/productdownloads?subfamily=VMware%20Workstation%20Pro 2.下载镜像dvd类型的,华为云官网下载,需要先注册,下载地址:https://mirrors.huaweicloud.com/mirro…

linux进程被杀掉日志,Linux进程突然被杀掉(OOM killer),查看系统日志

Linux进程被杀掉(OOM killer),查看系统日志 基本概念: Linux 内核有个机制叫OOM killer(Out Of Memory killer),该机制会监控那些占用内存过大,尤其是瞬间占用内存很快的进程,然后防止内存耗尽而自动把该进程杀掉。内核检测到系统内存不足、挑选并杀掉某个进程的过程可以参…

Salesforce开发入门指南:零基础学习宝典!

开发人员将Salesforce组织扩展到声明式配置之外,构建应用程序,进而优化业务运营。Salesforce开发人员通常会使用两种编程语言:Apex和JavaScript。 然而,Salesforce开发不仅仅只包括代码。为了在职业道路上脱颖而出,开发人员还需要了解声明性功能,将组织的设计和性能保持最…

Apache SeaTunnel社区首位学生Committer诞生!

采访对象 | 陈炳烨 采访人&编辑 | Debra Chen Apache SeaTunnel社区第一位学生Committer就此诞生!这位来自西安交通大学软件工程专业的同学从较为简单的文档修改工作,逐步深入到代码层面,到最后独立负责开发模块,为Apache SeaTunnel项目的发展添砖加瓦的同时,他本人也…