学习笔记:二分图

二分图

引入

二分图又被称为二部图。

二分图就是可以二分答案的图。

二分图是节点由两个集合组成,且两个集合内部没有边的图。换言之,存在一种方案,将节点划分成满足以上性质的两个集合。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

性质

如果两个集合中的点分别染成黑色和白色,可以发现二分图中的每一条边都一定是连接一个黑色点和一个白色点。换言之,二分图中不存在奇环。

证明:

​ 因为每一条边都是从一个集合走到另一个集合,只有走偶数次才可能回到同一个集合。

证毕。

判定

可以直接暴力枚举集合方案。

可以根据二分图性质来判断。考虑 dfs 或者 bfs 遍历整张图,如果图中不存在奇环则证明是二分图,反之则不是。

或者也可以考虑染色。如果存在冲突则证明不是二分图。

#include <iostream>
#include <cstring>
#define MAXN 100005
#define MAXM 200005
using namespace std;
int n, m, u, v, w;
struct edge{int to, nxt;}e[MAXM << 1];
int head[MAXN], cnt = 1;
int col[MAXN];
bool flag = true;
int read(){int t = 1, x = 0;char ch = getchar();while(!isdigit(ch)){if(ch == '-')t = -1;ch = getchar();}while(isdigit(ch)){x = (x << 1) + (x << 3) + (ch ^ 48);ch = getchar();}return x * t;
}
void write(int x){if(x < 0){putchar('-');x = -x;}if(x >= 10)write(x / 10);putchar(x % 10 ^ 48);
}
void add(int u, int v){cnt++;e[cnt].to = v;e[cnt].nxt = head[u];head[u] = cnt;cnt++;e[cnt].to = u;e[cnt].nxt = head[v];head[v] = cnt;
}
void dfs(int now, int color){for(int i = head[now] ; i != 0 ; i = e[i].nxt){if(flag == false)return;int v = e[i].to;if(col[v] == -1)col[v] = color,dfs(v, color ^ 1);else if(col[v] != color){flag = false;return;}}
}
int main(){n = read();m = read();for(int i = 1 ; i <= m ; i ++)u = read(),v = read(),add(u, v);memset(col, -1, sizeof(col));dfs(1, 1);if(flag == true)puts("Yes");else puts("No");return 0;
}

二分图最大匹配

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

解释(不正经版):可以把二分图左右两个集合分别想象成男生女生,匹配的过程就像是在相亲,最大匹配就是寻找一个方案能够相成最多对。

可以考虑将该问题转换成网络流问题来解决。

具体地,将源点连上左边所有点,右边所有点连上汇点,容量皆为 1 1 1。原来的每条边从左往右连边,容量也皆为 1 1 1,最大流即最大匹配。

如果使用Dinic 算法求该网络的最大流,可在 O ( n m ) O(\sqrt{n}m) O(n m) 求出。

洛谷 P3386【模板】二分图最大匹配

题目描述

给定一个二分图,其左部点的个数为 n n n,右部点的个数为 m m m,边数为 e e e,求其最大匹配的边数。

左部点从 1 1 1 n n n 编号,右部点从 1 1 1 m m m 编号。

输入格式

输入的第一行是三个整数,分别代表 n n n m m m e e e

接下来 e e e 行,每行两个整数 u , v u, v u,v,表示存在一条连接左部点 u u u 和右部点 v v v 的边。

输出格式

输出一行一个整数,代表二分图最大匹配的边数。

#include <iostream>
#include <cstring>
#include <queue>
#define MAXN 1005
#define MAXM 102005
using namespace std;
int n, m, t, u, v, w;
struct edge{int w, to, nxt;}e[MAXM];
int dep[MAXN], rad[MAXN], head[MAXN], cnt = 1;
queue <int> q;
int read(){int t = 1, x = 0;char ch = getchar();while(!isdigit(ch)){if(ch == '-')t = -1;ch = getchar();}while(isdigit(ch)){x = (x << 1) + (x << 3) + (ch ^ 48);ch = getchar();}return x * t;
}
void add(int u, int v, int w){cnt++;e[cnt].w = w;e[cnt].to = v;e[cnt].nxt = head[u];head[u] = cnt;
}
bool bfs(){while(!q.empty())q.pop();memset(dep, 0, sizeof(dep));dep[0] = 1;q.push(0);while(!q.empty()){int u = q.front();q.pop();rad[u] = head[u];for(int i = head[u] ; i != 0 ; i = e[i].nxt){if(dep[e[i].to] == 0 && e[i].w != 0){dep[e[i].to] = dep[u] + 1;q.push(e[i].to);if(e[i].to == n + m + 1)return true;}}}return false;
}
int dfs(int now, int flow){if(now == n + m + 1)return flow;int tmp = flow;for(int i = rad[now] ; i != 0 ; i = e[i].nxt){rad[now] = i;if(dep[e[i].to] == dep[now] + 1 && e[i].w != 0){int k = dfs(e[i].to, min(tmp, e[i].w));if(k == 0)dep[e[i].to] = 0;e[i].w -= k;e[i ^ 1].w += k;tmp -= k;}}return flow - tmp;
}
int dinic(){int ans = 0;while(bfs() == true)ans += dfs(0, 1e18);return ans;
}
int main(){n = read();m = read();t = read();for(int i = 1 ; i <= t ; i ++){u = read();v = read();add(u, n + v, 1);add(n + v, u, 0);}for(int i = 1 ; i <= n ; i ++)add(0, i, 1),add(i, 0, 0);for(int i = 1 ; i <= m ; i ++)add(n + i, n + m + 1, 1),add(n + m + 1, n + i, 0);cout << dinic() << endl;return 0;
}

二分图最大权匹配

一样的思路,转化为费用流模型。

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

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

相关文章

Pytorch代码入门学习之分类任务(二):定义数据集

一、导包 import torch import torchvision import torchvision.transforms as transforms 二、下载数据集 2.1 代码展示 # 定义数据加载进来后的初始化操作&#xff1a; transform transforms.Compose([# 张量转换&#xff1a;transforms.ToTensor(),# 归一化操作&#x…

【QT开发(15)】QT在没有桌面的系统中可以使用

在没有桌面的系统中&#xff0c;可以使用QT库。QT库可以在没有图形用户界面&#xff08;GUI&#xff09;的环境中运行&#xff0c;例如在服务器或命令行终端中。 这样就可利用Qt的&#xff1a; 对象模型&#xff0c;信号和槽容器类多线程和多进程网络编程 等

wiresharak捕获DNS

DNS解析&#xff1a; 过滤项输入dns&#xff1a; dns查询报文 应答报文&#xff1a; 事务id相同&#xff0c;flag里 QR字段1&#xff0c;表示响应&#xff0c;answers rrs变成了2. 并且响应报文多了Answers 再具体一点&#xff0c;得到解析出的ip地址&#xff08;最底下的add…

CentOS 编译安装 nginx

CentOS 编译安装 nginx 修改 yum 源地址为 阿里云 curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repoyum makecache升级内核和软件 yum -y update安装常用软件和依赖 yum -y install gcc gcc-c make cmake zlib zlib-devel openss…

环形链表(C++解法)

题目 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置&#…

【计算机网络】认识协议

目录 一、应用层二、协议三、序列化和反序列化 一、应用层 之前的socket编程&#xff0c;都是在通过系统调用层面&#xff0c;如今我们来向上打通计算机网络。认识应用层的协议和序列化与反序列化 我们程序员写的一个个解决我们实际问题, 满足我们日常需求的网络程序, 都是在应…

前端《中国象棋》游戏

源码下载地址 支持&#xff1a;远程部署/安装/调试、讲解、二次开发/修改/定制 查看视频 本程序是一个基于Html/css/javascrip的网页端象棋APP&#xff0c;其中引入JQuery来简便开发。 在程序中&#xff0c;使用一个Map二维数组来表示棋盘&#xff0c;通过给棋子设置不同的横坐…

FileWriter文件字符输出流

一.概念 以内存为基准&#xff0c;把内存中的数据以字符形式写出到文件中 二.构造器 public FileWriter(Filefile) 创建字节输出流管道与源文件对象接通 public FileWriter(String filepath) 创建字节输出流管道与源文件路径接通 public Filewriter(File file,boolean append) …

【MySQL】并发事务产生的问题及事务隔离级别

先来复习一下事务的四大特性&#xff1a; 原子性&#xff08;Atomicity&#xff09;&#xff1a;事务是不可分割的最小操作单位&#xff0c;事务中的所有操作要么全部执行成功&#xff0c;要么全部失败回滚&#xff0c;不能只执行其中一部分操作。一致性&#xff08;Consisten…

卷积神经网络的感受野

经典目标检测和最新目标跟踪都用到了RPN(region proposal network)&#xff0c;锚框(anchor)是RPN的基础&#xff0c;感受野(receptive field, RF)是anchor的基础。本文介绍感受野及其计算方法&#xff0c;和有效感受野概念。 1.感受野概念 在典型CNN结构中&#xff0c;FC层(…

vue核心面试题汇总【查缺补漏】

给大家推荐一个实用面试题库 1、前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;web前端面试题库 很喜欢‘万变不离其宗’这句话&#xff0c;希望在不断的思考和总结中找到Vue中的宗&#xff0c;来解答面试官抛出的…

FPGA设计时序约束七、设置时钟不确定约束

一、背景 在之前的时序分析中&#xff0c;通常是假定时钟是稳定理想的&#xff0c;即设置主时钟周期后按照周期精确的进行边沿跳动。在实际中&#xff0c;时钟是非理想存在较多不确定的影响&#xff0c;存在时延和波形的变化&#xff0c;要准确分析时序也需将其考虑进来&#x…

06 _ 链表(上):如何实现LRU缓存淘汰算法

今天我们来聊聊“链表(Linked list)”这个数据结构。学习链表有什么用呢?为了回答这个问题,我们先来讨论一个经典的链表应用场景,那就是LRU缓存淘汰算法。 缓存是一种提高数据读取性能的技术,在硬件设计、软件开发中都有着非常广泛的应用,比如常见的CPU缓存、数据库缓存…

“节省内存、提升性能:享元模式的神奇之处“

概念 享元模式的本质是缓存共享对象&#xff0c;降低内存消耗。 是对象池的的一种实现&#xff0c;一句话用到了缓存了对方和池化技术的地方绝大多是享元模式的体现。 例如线程池&#xff0c;数据库连接池&#xff0c;字符串常量池 应用示例 String中的享元模式 public c…

Linux Centos7安装后,无法查询到IP地址,无ens0,只有lo和ens33的解决方案

文章目录 前言1 查看network-scripts目录2 创建并配置 ifcfg-ens33 文件3 禁用NetworkManager4 重新启动网络服务总结 前言 在VMware中&#xff0c;安装Linux centos7操作系统后&#xff0c;想查询本机的IP地址&#xff0c;执行ifconfig命令 ifconfig结果如下&#xff1a; 结…

​ iOS自动混淆测试处理笔记

1 打开 ipa&#xff0c;导出ipa 路径和配置文件路径会自动填充 ​ 2 点击 开始自动混淆测试处理 自动混淆测试是针对 oc 类和oc方法这两个模块进行自动混淆ipa&#xff0c;并ipa安装到设备中运行&#xff0c;通过检测运行ipa包是否崩溃&#xff0c;来对oc类和oc方法进行筛选。…

Docker Harbor概述及构建

Docker Harbor概述及构建 一、Docker Harbor 概述1.1、harbor 简介1.2、Harbor的优势1.3、Harbor 的核心组件1.4、Docker私有仓库 架构 二、Harbor构建Docker私有仓库2.1 环境配置2.2、部署Harbor服务2.2.1、上传dock-compose&#xff0c;并设置权限2.2.2、安装harbor-offline-…

openEuler 22.03 LTS 环境使用 Docker Compose 一键部署 JumpServer (all-in-one 模式)

环境回顾 上一篇文章中&#xff0c;我们讲解了 openEuler 22.03 LTS 安装 Docker CE 和 Dcoker Compose&#xff0c;部署的软件环境版本分别如下&#xff1a; OS 系统&#xff1a;openEuler 22.03 LTS(openEuler-22.03-LTS-x86_64-dvd.iso)Docker Engine&#xff1a;Docker C…

归并排序(java)

大家好我是苏麟 , 今天说说归并排序 . 归并排序 递归 正式学习归并排序之前&#xff0c;我们得先学习一下递归算法。 定义&#xff1a; 定义方法时&#xff0c;在方法内部调用方法本身&#xff0c;称之为递归. public void show(){System.out.println("aaaa")…

软考高级系统架构师冲关预测

[ – 2023年10月27日 – ] 去年11月通过了软考高级系统架构师的考试&#xff0c;原本想立即分享下过关的总结回顾&#xff0c;但是随着软考新版大纲及教程的发布&#xff0c;也意味着题目及内容的复盘总结经验便不那么适用。在即将迎来今年的软考高架的时候&#xff0c;想着透…