学习笔记:二分图

news2024/12/26 13:57:43

二分图

引入

二分图又被称为二部图。

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

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

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

性质

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

证明:

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

证毕。

判定

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

可以根据二分图性质来判断。考虑 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.coloradmin.cn/o/1144015.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言之 结构体,枚举,联合

目录 1.结构体 1.1结构的基础知识 1.2结构的声明 1.3 特殊的声明 1.4 结构的自引用 1.5 结构体变量的定义和初始化 1.6 结构体内存对齐 1.7 修改默认对齐数 1.8 结构体传参 2. 位段 2.1 什么是位段 2.2位段的内存分配 2.3 位段的跨平台问题 3. 枚举 3.1 枚举类型…

Mybatis简介(二)

1、多表映射 简介一 链接 对于数据库的操作&#xff0c;很多时候我们都是在多表的基础上进行操作的&#xff0c;在这里讲一下多表属性值与列名映射。 案例&#xff1a;这里有一个订单表和一个客户表 CREATE TABLE t_customer (customer_id INT NOT NULL AUTO_INCREMENT, cus…

在 Elasticsearch 中丰富你的 Elasticsearch 文档

作者&#xff1a;David Pilato 对于 Elasticsearch&#xff0c;我们知道联接应该在 “索引时” 而不是查询时完成。 本博文是一系列三篇博文的开始&#xff0c;因为我们可以在 Elastic 生态系统中采取多种方法。 我们将介绍如何在 Elasticsearch 中做到这一点。 下一篇博文将介…

node实战——后端koa结合jwt连接mysql实现权限登录(node后端就业储备知识)

文章目录 ⭐前言⭐ 环境准备⭐ 实现过程⭐ mysql 配置⭐路由前的准备⭐账号注册生成token⭐账号登录生成token⭐token登录 ⭐ 自测过程截图⭐总结⭐结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本文分享关于node实战——后端koa项目配置jwt实现登录注册&#xff08;n…

1230. K倍区间(前缀和)

题目&#xff1a; 1230. K倍区间 - AcWing题库 突破口&#xff1a; 区间遍历枚举一般先枚举右端点&#xff0c;再枚举左端点&#xff0c;注意由右端点限制左端点 思路&#xff1a;1.暴力 #include<cstdio> #include<iostream> #include<algorithm> #incl…

Win 7 VPN拨号错误734.

正在验证用户名和密码错误 734: PPP 链接控制协议终止。 如果您继续收到错误信息&#xff0c;您可以启用日志记录来做分析。 其他电脑拨号都成功.就这个电脑不行.找了很久,修改之后报好成功 ************************** 找到是跟下面两个两个注册表信息有关,尤其是第一个我…

基于Pytest+Requests+Allure实现接口自动化测试!

一、整体结构 框架组成&#xff1a;pytestrequestsallure设计模式&#xff1a; 关键字驱动项目结构&#xff1a; 工具层&#xff1a;api_keyword/参数层&#xff1a;params/用例层&#xff1a;case/数据驱动&#xff1a;data_driver/数据层&#xff1a;data/逻辑层&#xff1a…

75 寻找旋转排序数组中的最小值

寻找旋转排序数组中的最小值 题解1 一次循环(正确理解题意)题解2 二分 已知一个长度为 n 的数组&#xff0c;预先按照 升序排列&#xff0c;经由 1 到 n 次 旋转 后&#xff0c;得到输入数组。例如&#xff0c;原数组 nums [0,1,2,4,5,6,7] 在变化后可能得到&#xff1a; …

刚刚:2023阿里云双十一优惠活动上线了!

2023阿里云双十一优惠活动「金秋云创季」开始啦&#xff0c;10月27日到10月31日可以领满减优惠&#xff0c;到11月1日和11月11日之间可以购买云服务器等产品&#xff0c;11.12到11.30日赢最高百万上云抵扣金&#xff0c;阿里云百科aliyunbaike.com分享2023阿里云双十一优惠活动…

Xray的简单使用

xray 简介 xray 是一款功能强大的安全评估工具&#xff0c;由多名经验丰富的一线安全从业者呕心打造而成&#xff0c;主要特性有: 检测速度快。发包速度快; 漏洞检测算法效率高。支持范围广。大至 OWASP Top 10 通用漏洞检测&#xff0c;小至各种 CMS 框架 POC&#xff0c;均…

前端实现打印功能Print.js

前端实现打印的方式有很多种&#xff0c;本人恰好经历了几个项目都涉及到了前端打印&#xff0c;目前较为推荐Print.js来实现前端打印 话不多说&#xff0c;直接上教程 官方链接: Print.js官网 在项目中如何下载Print.js 使用npm下载&#xff1a;npm install print-js --sav…

python 从mssql取出datetime2类型之后格式化

我mssql是datetime2类型&#xff0c;用df取出之后发现是个纳秒的int&#xff08;1698419713000000000 这种&#xff09; 所以格式化的话就需要变成秒为单位&#xff0c;他们之间是10的9次方倍。所以先除以1e9之后用datetime.datetime.fromtimestamp()转换之后再format就行了 l…

CCF CSP认证历年题目自练 Day39

题目 试题编号&#xff1a; 201312-5 试题名称&#xff1a; I’m stuck! 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 256.0MB 问题描述&#xff1a; 问题描述   给定一个R行C列的地图&#xff0c;地图的每一个方格可能是’#‘, ‘’, ‘-’, ‘|’, ‘.’, ‘S’, ‘…

系列十九、循环依赖(一)

一、概述 循环依赖是指&#xff0c;多个bean之间相互依赖&#xff0c;形成了一个闭环。比如A依赖于B、B依赖于C、C依赖于A&#xff0c;形成了一个圈。 二、两种方式对循环依赖的影响 2.1、官网说明 2.2、结论 我们AB循环依赖问题只要A的注入方式是setter、并且是singleton&am…

Android14 WMS启动流程

一 概述 本文Android14源代码可参考&#xff1a;Search 在 Android 系统中&#xff0c;从设计的角度来看&#xff0c;窗口管理系统是基于 C/S 模式的。整个窗口系统分为服务端和客户端两大部分&#xff0c;客户端负责请求创建窗口和使用窗口&#xff0c;服务端完成窗口的维护…

智慧工地管理系统源码-数字孪生智慧工地可视化解决方案

一、智慧工地建设背景 我国经济发展正从传统粗放式的高速增长阶段&#xff0c;进入高效率、低成本、可持续的中高速增长阶段。随着现代建筑的复杂度和体量等不断增加&#xff0c;施工现场管理的内容越来越多&#xff0c;管理的技术难度和要求在不断提高。传统的施工现场管理模…

用超声波清洗机洗眼镜的有哪些?清洁力强的超声波清洗机不能错过

超声波清洗机在清洗眼镜方面表现出色&#xff0c;其强大的清洁能力可以彻底清除眼镜上的污垢和细菌。这种清洗方式被认为是一种高效且卫生的清洁方式&#xff0c;因为它利用高频振动和微射流打击力来清除污垢和细菌&#xff0c;而不是使用化学物质。对于那些长时间佩戴眼镜或者…

windows + ubuntu + vscode开发环境配置安装

一、卸载WSL/WSL2 如果安装了windows子系统的朋友&#xff0c;可以选择继续使用。或者提前卸载WSL&#xff0c;再选择安装虚拟机。虚拟机占用内存较大&#xff0c;WSL可能对于开发的一些需求还有欠缺。根据自己的实际情况进行选择。 WIN10/11安装WSL(请参考官方资料&#xff0c…

TSINGSEE青犀智慧仓储可视化视频智能监管系统方案

一、背景与需求 对于现在很多大型工厂或者物流基地来说&#xff0c;仓库无疑是存放物品的重点场所。仓储存放着大量货物&#xff0c;同时存在大量的辅助设备&#xff0c;需要进行全方位的监管&#xff0c;以避免发生安全事故&#xff0c;造成财产损失。原有的人工巡检方式已无…

Ubuntu安装AdGuardhome(树莓派安装AdGuardhome)

Ubuntu安装AdGuardhome&树莓派安装AdGuardhome 1.什么是AdGuardhome2.设备情况3.3.1.下载AdGuardhome3.2.解压3.3.安装3.4.仪表盘配置3.5.dns黑名单添加3.6.DNS白名单设置3.7常规设置3.8. dns设置3.9.加密设置 4.客户端设置 1.什么是AdGuardhome AdGuard Home 是网络范围的…