网站素材免费下载公司宣传册设计与制作图片
网站素材免费下载,公司宣传册设计与制作图片,网站开发怎么用自己的电脑,网站建设论坛社区目录 二分图概念
二分图应用场景
如何判定一个图是否可以划分成二分图 证明
染色法
原理步骤
时间复杂度
算法思路 例子
匈牙利算法 概念
匈牙利使用算法前提,场景
时间复杂度 算法思路
例子 二分图概念 二分图是图论中的一个重要概念#xff0c;指的是一个图的…目录 二分图概念
二分图应用场景
如何判定一个图是否可以划分成二分图 证明
染色法
原理步骤
时间复杂度
算法思路 例子
匈牙利算法 概念
匈牙利使用算法前提,场景
时间复杂度 算法思路
例子 二分图概念 二分图是图论中的一个重要概念指的是一个图的顶点集可以被分为两个互不相交的子集并且图中的每条边都连接两个不同子集中的顶点。换句话说如果一个图是二分图那么可以将图中的所有顶点分为两组使得每条边的两个端点分别属于不同的组。
二分图应用场景 匹配问题在二分图中匹配问题是指找到一种边的子集使得图中每个顶点都与子集中的某条边相邻。在实际应用中可以用于匹配求职者和工作岗位、学生和导师等场景。 任务分配在二分图中任务分配问题是指将一组任务分配给一组工人使得每个任务只被分配给一个工人每个工人最多只能完成一个任务。这在实际生活中可以用于工作排班、资源分配等问题。 流网络在网络流问题中二分图可以表示一种特殊的流网络其中顶点集分为源点集和汇点集边表示从源点到汇点的流量路径用于建模输送网络中的流量分配和优化问题。 电路布线在电路布线问题中可以将待连接的元器件和连接线分别看作二分图中的顶点和边通过最小化连接线的长度或者最小化连接的总成本来优化电路的布线。 等等
如何判定一个图是否可以划分成二分图 二分图当且仅当图中不含有奇数环 证明
充分性不含有奇数环的图可以划分成二分图 使用一种方法染色法随意选择 图中一个点 将其分到集合 然后将其邻接的所有点分到集合 再将分到 的点的邻接点分到 。以此类推因为图中不含有奇数环所以分类过程中一定没有矛盾。 如何证明没有矛盾 反证假设图中不含有奇数环但分类过程中出现了矛盾。 假设有一个偶环 任意相邻两点有边连接且 和 之间有一条边相邻。该环中出现了矛盾使用染色法时 和 被分到同一个类别 。 首先我们先对该环按顺序依次进行分类 分到 分到 分到 。 以此类推可知编号为奇数的都属于 集合编号为偶数的都属于 集合。因此 被分到 。并且 相邻 也应该分到 。 与假设不符因此假设错误说明图中不含有奇数环分类过程中一定没有矛盾。
必要性二分图不含有奇数环 反证假设该二分图含有一个奇数环任意相邻两点有边连接且 和 之间有一条边相邻。 假设 集合则 。以此类推可知编号为奇数的都属于 集合编号为偶数的都属于 集合。 那么 和 都属于 集合 和 之间有一条边。与二分图同一个集合中的点不相连矛盾因此假设错误。二分图不存在奇数环。 染色法
判断一个图是不是二分图。
原理步骤
选择一个起始顶点将其染成一种颜色比如红色。将与该顶点相邻的顶点染成另一种颜色比如蓝色。依次对与 已染色的顶点 相邻的未染色顶点进行染色要求相邻顶点的颜色不能相同。如果在染色的过程中发现有相邻的两个顶点被染成了相同的颜色则说明该图不能划分成二分图否则当所有顶点都被染色后该图可以划分成二分图。
时间复杂度 O(mn)
算法思路 可以使用bfsdfs并查集遍历图。 伪代码 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 dfsAcWing 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 Queueint[] 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 i1;in;i) { // 有可能有多个连通图因此每个点都需要遍历if(!st[i]) { // 如果没被染色q.add(new int[]{i,1}); // 染色为1st[i] true;if(color()-1) flag 0; // 如果有奇数环返回-1}}if(flag0) 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 ih[u];i!-1;ine[i]){ // 对邻接点进行染色int j e[i];if(w[j]weight||ju) 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。
匈牙利使用算法前提,场景 已知该图是二分图求最大匹配数。 可以想象成二分图左边集合是女生右边是男生两个集合之间男生和女生连接了线表明这两人可以成为恋爱关系。但是一个男生只能和一个女生谈恋爱求最多能成为恋爱关系的情侣数量。 任务分配在任务与执行者之间存在偏好关系时可以使用匈牙利算法将任务分配给执行者使得每个执行者最多承担一个任务并且尽可能多的任务得到执行。 最大流问题匈牙利算法可以用作最大流算法的一部分用于寻找增广路径从而找到最大流量。 资源分配在资源有限的情况下可以使用匈牙利算法来优化资源的分配以满足不同资源需求的任务或需求者。 时间复杂度 O(mn)实际一般小于mn 算法思路 该二分图中一个集合 中有 个顶点另一个集合 中有 个顶点。 st[ ] 伪代码 // 用 匹配 只需要记录 到 的单向边 mian(): 循环 n1 次 对该点进行匹配 : 遍历 点所有能匹配上的 中的所有点 如果 当前匹配到的点 没有匹配过 或者 点被匹配了但是匹配到的 中的那个点可以匹配 中另外的点 那么点 和 点匹配成功 遍历完还没匹配到则匹配失败 例子 给定一个二分图其中左半部包含 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 i1;in1;i){Arrays.fill(st,false); // 被考虑过的n2集合中的点也可以重新被下一个n1中的点考虑if(find(i)) res; // 找n2中能匹配的}System.out.println(res);}// 进行匹配public static boolean find(int u){for(int ih[u];i!-1;ine[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.mzph.cn/diannao/88333.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!