二分图---染色法(判断二分图),匈牙利算法(二分图的最大匹配) //概念,应用场景,判定证明,算法思路,示例

目录

 二分图概念

二分图应用场景

如何判定一个图是否可以划分成二分图

    证明

染色法

原理步骤

时间复杂度

算法思路

 例子   

匈牙利算法

 概念

匈牙利使用算法前提,场景

时间复杂度

 算法思路

例子 


 二分图概念

        二分图是图论中的一个重要概念,指的是一个图的顶点集可以被分为两个互不相交的子集,并且图中的每条边都连接两个不同子集中的顶点。换句话说,如果一个图是二分图,那么可以将图中的所有顶点分为两组,使得每条边的两个端点分别属于不同的组。

二分图应用场景

  1. 匹配问题:在二分图中,匹配问题是指找到一种边的子集,使得图中每个顶点都与子集中的某条边相邻。在实际应用中,可以用于匹配求职者和工作岗位、学生和导师等场景。

  2. 任务分配:在二分图中,任务分配问题是指将一组任务分配给一组工人,使得每个任务只被分配给一个工人,每个工人最多只能完成一个任务。这在实际生活中可以用于工作排班、资源分配等问题。

  3. 流网络:在网络流问题中,二分图可以表示一种特殊的流网络,其中顶点集分为源点集和汇点集,边表示从源点到汇点的流量路径,用于建模输送网络中的流量分配和优化问题。

  4. 电路布线:在电路布线问题中,可以将待连接的元器件和连接线分别看作二分图中的顶点和边,通过最小化连接线的长度或者最小化连接的总成本来优化电路的布线。

  5. 等等

如何判定一个图是否可以划分成二分图

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

    证明

  • 充分性:(不含有奇数环的图可以划分成二分图)

       使用一种方法(染色法),随意选择 A 图中一个点 a ,将其分到集合 A_x ,然后将其邻接的所有点分到集合 A_y ,再将分到 A_y 的点的邻接点分到 A_x 。以此类推,因为图中不含有奇数环,所以分类过程中一定没有矛盾

        如何证明没有矛盾:

        反证:假设图中不含有奇数环,但分类过程中出现了矛盾。

        假设有一个偶环 a_1,\ a_2\ ,a_3\ ...\ a_{2k} \ \ k\in N^+ (任意相邻两点有边连接,且 a_1 和 a_{2k} 之间有一条边相邻)。该环中出现了矛盾,使用染色法时, a_1 和 a_{2k} 被分到同一个类别 A_x

        首先,我们先对该环按顺序依次进行分类,a_1 分到 A_xa_2 分到 A_ya_3 分到 A_x 。

        以此类推,可知编号为奇数的都属于 A_x 集合,编号为偶数的都属于 A_y 集合。因此 , a_{2k} 被分到 A_y 。并且,a_1 相邻 a_{2k} ,a_{2k}也应该分到 A_y

        与假设不符,因此假设错误,说明图中不含有奇数环,分类过程中一定没有矛盾。

  • 必要性:(二分图不含有奇数环)

        反证:假设该二分图含有一个奇数环a_1,\ a_2\ ,a_3\ ...\ a_{2k-1} \ \ k\in N^+,任意相邻两点有边连接,且 a_1 和 a_{2k-1} 之间有一条边相邻。

        假设 a_1\in A_x 集合,则 a_2\in A_y ,a_3\in A_x。以此类推,可知编号为奇数的都属于 A_x 集合,编号为偶数的都属于 A_y 集合。

        那么 a_1 和 a_{2k-1} 都属于 A_x 集合,a_1 和 a_{2k-1} 之间有一条边。与二分图同一个集合中的点不相连矛盾,因此假设错误。二分图不存在奇数环。



染色法

判断一个图是不是二分图。

原理步骤

  1. 选择一个起始顶点,将其染成一种颜色(比如红色)。
  2. 将与该顶点相邻的顶点染成另一种颜色(比如蓝色)。
  3. 依次对与 已染色的顶点 相邻的未染色顶点进行染色,要求相邻顶点的颜色不能相同。
  4. 如果在染色的过程中,发现有相邻的两个顶点被染成了相同的颜色,则说明该图不能划分成二分图;否则,当所有顶点都被染色后,该图可以划分成二分图。

时间复杂度

        O(m+n)

算法思路

        可以使用bfs,dfs,并查集遍历图。 

伪代码 BFS版:

main:

        Queue q

        循环n次  // 有可能有多个连通图

                如果当前点 t 没被访问过,q <- t

                对 t 进行染色

                进行bfs()

bfs():

        while q 不空:

                t <- 取出队头

                遍历 t 的邻接的点:

                        如果邻接的点的色与 t 的颜色相同或者是个自环 说明不能构成一个二分图

                        否则:将邻接点染色,并加入队列

 例子   

860. 染色法判定二分图 - AcWing题库

给定一个 n 个点 m 条边的无向图,图中可能存在重边和自环。

请你判断这个图是否是二分图。

输入格式

第一行包含两个整数 n 和 m。

接下来 m 行,每行包含两个整数 u 和 v,表示点 u 和点 v 之间存在一条边。

输出格式

如果给定图是二分图,则输出 Yes,否则输出 No

数据范围

1≤n,m≤10^5

输入样例:

4 4
1 3
1 4
2 3
2 4

输出样例:

Yes

dfs:AcWing 860. 染色法判定二分图 - JAVA -DFS - AcWing 

并查集:AcWing 860. 看不懂dfs和bfs可以来康康并查集 - AcWing 

使用BFS + 数组模拟邻接表: 

import java.io.*;
import java.util.*;class Main{static int N = 100010;static int n,m,idx;static int[] h = new int[N];static int[] e = new int[2*N];static int[] ne = new int[2*N];static int[] w = new int[N]; // 染色记录static boolean[] st = new boolean[N]; // 标记是否染过色static Queue<int[]> q = new LinkedList<>();public static void main(String[] args) throws IOException{BufferedReader in = new BufferedReader(new InputStreamReader(System.in));String[] s = in.readLine().split(" ");n = Integer.parseInt(s[0]);m = Integer.parseInt(s[1]);Arrays.fill(h,-1);int flag = 1;while(m-->0){s = in.readLine().split(" ");int a = Integer.parseInt(s[0]);int b = Integer.parseInt(s[1]);add(a,b);add(b,a);  }for(int i=1;i<=n;i++) { // 有可能有多个连通图,因此每个点都需要遍历if(!st[i]) { // 如果没被染色q.add(new int[]{i,1}); // 染色为1st[i] = true;if(color()==-1) flag = 0; // 如果有奇数环,返回-1}}if(flag==0) System.out.println("No");else System.out.println("Yes");}// 染色public static int color(){while(!q.isEmpty()){int[] t = q.poll();int u = t[0]; // 点int weight = t[1]; // 被染色的值for(int i=h[u];i!=-1;i=ne[i]){ // 对邻接点进行染色int j = e[i];if(w[j]==weight||j==u) return -1; // 如果该点的颜色与邻接点相同或者有自环,直接返回if(!st[j]){ // 如果该点没被染色w[j] = 3-weight; // 染色q.add(new int[]{j,w[j]});  st[j] = true; // 表示为已经被访问过} }}return 1;}// 添加边public static void add(int a,int b){e[idx] = b;ne[idx] = h[a];h[a] = idx++;}
}

匈牙利算法

 概念

  •  匹配:在图论中,一个「匹配」是一个边的集合,其中任意两条边都没有公共顶点。
  • 最大匹配:一个图所有匹配中,所含匹配边数最多的匹配,称为这个图的最大匹配。
  • 完美匹配:如果一个图的某个匹配中,所有的顶点都是匹配点,那么它就是一个完美匹配。
  • 交替路:从一个未匹配点出发,依次经过非匹配边、匹配边、非匹配边…形成的路径叫交替路。
  • 增广路:从一个未匹配点出发,走交替路,如果途径另一个未匹配点(出发的点不算),则这条交替 路称为增广路(agumenting path)。

匈牙利使用算法前提,场景

        已知该图是二分图,求最大匹配数。

        可以想象成:二分图,左边集合是女生,右边是男生,两个集合之间男生和女生连接了线,表明这两人可以成为恋爱关系。但是一个男生只能和一个女生谈恋爱,求最多能成为恋爱关系的情侣数量。

        

  1. 任务分配:在任务与执行者之间存在偏好关系时,可以使用匈牙利算法将任务分配给执行者,使得每个执行者最多承担一个任务,并且尽可能多的任务得到执行。

  2. 最大流问题:匈牙利算法可以用作最大流算法的一部分,用于寻找增广路径,从而找到最大流量。

  3. 资源分配:在资源有限的情况下,可以使用匈牙利算法来优化资源的分配,以满足不同资源需求的任务或需求者。

时间复杂度

        O(mn),实际一般小于mn 

 算法思路

        该二分图中,一个集合A_1 中有 n_1 个顶点,另一个集合A_2 中有 n_2 个顶点。

        st[ ] :

伪代码:

// 用 A_1 匹配 A_2 ,只需要记录 A_1 到 A_2 的单向边

mian():

循环 n1 次:

        对该点进行匹配 find(t)

find(t):

        遍历 t 点所有能匹配上的 A_2 中的所有点:

                如果 当前匹配到的点 i 没有匹配过 或者 i 点被匹配了,但是匹配到的 A_1 中的那个点可以匹配 A_2 中另外的点

                那么点 i 和 t 点匹配成功

        遍历完还没匹配到则匹配失败

例子 

 给定一个二分图,其中左半部包含 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≤10^5

输入样例:

2 2 4
1 1
1 2
2 1
2 2

输出样例:

2
// 通过n1集合匹配n2集合,只需记录n1到n2的边
import java.io.*;
import java.util.*;class Main{static int N = 510, M = 100010;static int n1,n2,m,idx,res;static int[] h = new int[N];static int[] e = new int[M];static int[] ne = new int[M];static boolean[] st = new boolean[N]; // n2中的点是否匹配了static int[] match = new int[N]; // 记录n2集合中的点匹配的是n1中的哪个点public static void main(String[] args) throws IOException{BufferedReader in = new BufferedReader(new InputStreamReader(System.in));String[] s = in.readLine().split(" ");n1 = Integer.parseInt(s[0]);n2 = Integer.parseInt(s[1]);m = Integer.parseInt(s[2]);Arrays.fill(h,-1);while(m-->0){s = in.readLine().split(" ");int a = Integer.parseInt(s[0]);int b = Integer.parseInt(s[1]);add(a,b); // 只需要添加单向边}for(int i=1;i<=n1;i++){Arrays.fill(st,false); // 被考虑过的n2集合中的点也可以重新被下一个n1中的点考虑if(find(i)) res++; // 找n2中能匹配的}System.out.println(res);}// 进行匹配public static boolean find(int u){for(int i=h[u];i!=-1;i=ne[i]){int j = e[i];if(!st[j]){st[j] = true; // 被当前点考虑到了if(match[j]==0||find(match[j])){ // 如果该点没有匹配或者该点的上一个匹配的点可以匹配到另外一个match[j] = u; // 将j匹配给ireturn true; // 匹配成功                    } }}return false;}// 添加边public static void add(int a,int b){e[idx] = b;ne[idx] = h[a];h[a] = idx++;}
}

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

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

相关文章

APRISO的低代码能力降低MOM系统全生命周期成本

前言 进入21世纪以来企业之间的竞争发生了巨大的变化&#xff0c;特别是近10年来&#xff0c;客户对产品的需求逐渐多样化&#xff0c;制造企业的生产模式也开始由大批量的刚性生产变为了多品种、小批量的柔性生产模式&#xff0c;生产线也从以前的手工方式转为了以自动化的机…

selenium 爬虫的数据实战

引言 众所周知&#xff0c;Python 有很多的爬虫工具&#xff0c;例如&#xff0c;requests、scrapy、selenium等。但是爬虫有个最难搞的东西就是反爬虫了&#xff0c;使用 requests、scrapy框架爬取速度飞快&#xff0c;但是遇到反爬的网站就得斗智斗勇半天甚至好几天。因此&a…

2024年2月深度学习的论文推荐

我们这篇文章将推荐2月份发布的10篇深度学习的论文 Beyond A*: Better Planning with Transformers via Search Dynamics Bootstrapping. https://arxiv.org/abs/2402.14083 Searchformer是一个基于Transformer架构的人工智能模型&#xff0c;经过训练可以模拟A星寻路算法&a…

【重要公告】BSV区块链协会宣布将启动多项动态安全增强措施

​​发表时间&#xff1a;2024年2月16日 2024年2月16日&#xff0c;瑞士楚格 - BSV区块链协议的管理机构BSV区块链协会&#xff08;以下简称“BSV协会”&#xff09;宣布对其运营模式实施全新的安全架构&#xff0c;其中包括引入网络访问规则和数字资产找回协议&#xff0c;以及…

分享一点PDF中获取表格的探索过程

版面分析&#xff1a;如何得到标题、如何的得到段落&#xff08;正确的段落&#xff09;、如何得到表格、如何得到图片&#xff0c;图和得到图片上的文字&#xff1f; 还有细节问题&#xff1a;双栏和多栏的问题、公式问题 扫描件&#xff1a;扫描件本质上是图片&#xff0c;如…

Java 网络通信

两台或多台设备通过一定物理设备连接起来构成了网络。 根据网络的覆盖范围不同&#xff0c;对网络分类&#xff1a; 局域网&#xff1a;覆盖范围小&#xff0c;仅仅覆盖一个教室或一个机房。城域网&#xff1a;覆盖范围较大&#xff0c;可以覆盖一个城市。广域网&#xff1a;…

Python轴承故障诊断 (14)高创新故障识别模型

目录 往期精彩内容&#xff1a; 创新点&#xff1a; 前言 1 模型整体结构 1.1 模型整体结构如下所示&#xff1a; 1.2 创新点详细介绍&#xff1a; 2 轴承故障数据的预处理 2.1 导入数据 2.2 故障FFT变换可视化 2.3 故障VMD分解可视化 2.4 故障数据的特征预处理数据集…

基于B/S+MySQL+Tomcat开发的旅游信息管理系统

基于B/SMySQLTomcat开发的旅游信息管理系统 项目介绍&#x1f481;&#x1f3fb; 塞北村镇旅游网站设计主要用于实现旅游景点信息管理&#xff0c;基本功能包括&#xff1a;主界面模块设计&#xff0c;用户注册模块&#xff0c;旅游景点模块&#xff0c;酒店预订模块&#xff0…

如何利用IP代理高效采集产品数据,打造爆品?

文章目录 一、什么是网络爬虫&#xff1f;二、普通人如何通过网络爬虫赚钱&#xff1f;2.1、心得分享2.2、工具自动化收集信息 三、 动态IP代理3.1、覆盖范围3.2、性价比3.3、教程中心F&Q使用教程 3.4、在网络数据采集中的重要性 四、实战应用案例一&#xff1a;ebay电商【…

C++面试常见八股分享

1.unordered_set和set&#xff0c;unordered_map和map的区别 set 和 map 是 C STL 中的两种关联容器&#xff0c;而 unordered_set 和 unordered_map 是 C11 新增的基于哈希表的关联容器。它们之间的主要区别在于底层的数据结构和操作复杂度。 set 和 unordered_set&#xff1…

IntelliJ IDEA 常用快捷键和下载链接

下载链接&#xff08;windows&#xff09; 下载 IntelliJ IDEA – 领先的 Java 和 Kotlin IDE 编码时&#xff1a; 跳转到引用方法的地方 &#xff08;有多个引用时会出现下拉列表&#xff09; ctrl鼠标左键 跳转后回到原来的地方 …

uniapp:启动图 .9png 制作教程

1、工具安装&#xff1a;自行下载Android Studio 2、制作.9png 注意上图3条黑线的位置&#xff0c;意思是&#xff1a;标注黑线的位置可以进行缩放。 对其大多数启动图来说&#xff0c;标注以上3条黑线即可。