寒假Day9:二分图的判断+匈牙利算法
二分图匹配相关概念
给定一个二分图G,在G的一个子图M中,M的边集{E}中的任意两条边都不依附于同一个顶点,则称M是一个匹配。
极大匹配是指在当前已完成的匹配下,无法再通过增加未完成匹配的边的方式来增加匹配的边数。
最大匹配是所有极大匹配当中边数最大的一个匹配。选择这样的边数最大的子集称为图的最大匹配问题。
如果一个匹配中,图中的每个顶点都和图中某条边相关联,则称此匹配为完全匹配,也称作完备匹配。
求解算法:求二分图匹配可以用最大流(Maximal Flow)或者匈牙利算法。
注意:完全匹配一定是极大匹配,但是极大匹配不一定是完全匹配。
交替路:从一个未匹配的点出发,依次经过未匹配边、匹配边、未匹配边....这样的路叫做交替路。
增广路:从一个未匹配的点出发,走交替路,到达了一个未匹配过的点,这条路叫做增广路。
看下图,其中1、4、5、7是已经匹配的点,1->5,4->7是已经匹配的边,那么我们从8开始出发,8->4->7->1->5->2这条路就是一条增广路。
二分图的判断
对于二分图的问题我们首先要判断一个图它是不是二分图。
对于二分图的判断方法最常见的是染色法(对每一个点进行染色操作,我们只用黑白两种颜色,问能不能使所有的点都染上了色,而且相邻两个点的颜色不同,如果可以那么这个图就是一个二分图)。
对于判断是否是一个二分图的方法可以用dfs和bfs两种方式去实现。
bfs判断二分图:
1 bool bfs()//用bfs 判断一幅图是否是二分图 2 { 3 memset(col,0,sizeof(col)); 4 //染色后的状态只有1和-1 5 //所以染色的初始状态为全部清空为0 6 queue<int> Q; 7 Q.push(1);//先让第一个点入队 8 col[1]=1;//给第一个点染色为1 9 while(!Q.empty()) 10 { 11 int p=Q.front(); 12 Q.pop(); 13 for(int i=0; i<v[p].size(); i++) 14 { 15 //找与第一个点相邻的点 16 int x=v[p][i]; 17 if(col[x]==0)//如果未被染色 18 { 19 col[x]=-col[p];//就染成与当前点相反的颜色 20 Q.push(x); 21 } 22 else//如果已经被染色了且和当前节点染色相同,则确定不是二分图 23 { 24 if(col[p]==col[x]) 25 return 0; 26 } 27 } 28 } 29 return 1; 30 }
匈牙利算法
时间复杂度:O(n*m)
匈牙利算法模板:
1 bool dfs(int x) 2 { 3 for(int i=0; i<v[x].size(); i++) 4 { 5 int s=v[x][i]; 6 if(book[s]==0) // 判断是否标记过,没有被标记进行下一步 7 { 8 book[s]=1; 9 if(f[s]==-1||dfs(f[s])) // 如果没有被匹配过且能和其他的点进行匹配 10 { 11 f[s]=x; 12 return 1; 13 } 14 } 15 } 16 return 0; 17 }
补充:
- 匈牙利算法得到的最大匹配并不是唯一的,预设匹配边、或者匹配顺序不同等,都可能会导致有多种最大匹配情况,所以有一种替代KM算法的想法是,我们只需要用匈牙利算法找到所有的最大匹配,比较每个最大匹配的权重,再选出最大权重的最优匹配即可得到更贴近真实情况的匹配结果。但这种方法时间复杂度较高,会随着目标数越来越多,消耗的时间大大增加,实际使用中并不推荐。
- 匈牙利算法是最简单最常见的求最大匹配数的算法,但是它的时间复杂度是O(n*m),对于一般的题来说最多有500个点,所以匈牙利是最好的做法。
- 假如遇到点数更多的话,可以使用Hopcroft-Karp算法,它的时间复杂度是O(n^(1/2) * m)。
- 以后碰到更深的题目再去学习一下HK算法、KM算法(带权二分图的最优匹配问题)、匈牙利算法求二分图多重匹配。
小知识点:
- Have all the workers punched in yet?
所有工人上班都打卡了吗? punch in 打卡 ~on time - abs是求一个整数的绝对值,fabs是求一个实数的绝对值
- 数组开小了不会显示RE,会提示超时
可参考博客:
https://blog.csdn.net/dark_scope/article/details/8880547
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」