博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
二分图匹配
阅读量:5246 次
发布时间:2019-06-14

本文共 1542 字,大约阅读时间需要 5 分钟。

不严格说明什么是二分图 ==> 能将图的顶点分为两个集合、同一集合中的顶点没有边相连

匹配 ==> 在图G中两两没有公共端点的边集合M ⊆ 边集合E

除了匹配顺便说一些其他的术语

边覆盖 ==> 在图G中任意顶点都至少是F中某条边的端点的边集合F ⊆ E

独立集 ==> 在G中两两互不相连的顶点集合S ⊆ V

顶点覆盖 ==> 在G中任意边都至少一个端点属于S的顶点集合 S ⊆ V

即 匹配 && 边覆盖 属于边的集合、独立集 && 顶点覆盖 属于顶点的集合

其中有一些这样子的关系

V = 最大匹配 + 最小边覆盖 = 最大独立集合 + 最小顶点覆盖

其中最大独立集合和最小顶点覆盖在非二分图下都是 NP-Hard 问题

而在二分图下有 ==> 最大匹配 = 最小顶点覆盖

这一性质使得需要求顶点覆盖的题目在分析出是二分图后可以转化为匹配解决

 

求二分图匹配的算法有

① 转化为最大流

将原图中的所有无向边改成有向边,方向从顶点集合U到顶点集合V,定义边容量为 1

然后建立一个超级源点连接容量为 1 的边到 U 的各个顶点

同样建立超级汇点并从 V 的各个顶点连接容量为 1 的边到超级汇点

最后求出此图的最大流就是最大匹配了,算法复杂度为 O(V*E)

②匈牙利算法( KM算法 )

匈牙利算法是利用一个结论

增广路中的匹配边永远比未匹配边多一条

所以可以不断在二分图中去寻找增广路,然后来交换匹配和未匹配边的关系

来达到“蹭出”空间的办法,最后加大匹配数

具体的有推荐两篇博客 ==> 、

这里直接给出模板,用邻接表实现的复杂度为 O(V*E)

#include
#include
using namespace std;const int maxn = 1e3 + 10;const int maxm = 1e4 + 10;struct EDGE{ int v, nxt; }Edge[maxm];int Head[maxn], cnt;int N, M;int match[maxn];bool used[maxn];inline void init(){ for(int i=0; i<=N; i++) Head[i] = -1; cnt = 0;}inline void AddEdge(int from, int to){ Edge[cnt].v = to; Edge[cnt].nxt = Head[from]; Head[from] = cnt++;}bool DFS(int v){ used[v] = true; for(int i=Head[v]; i!=-1; i=Edge[i].nxt){ int Eiv = Edge[i].v; int w = match[Eiv]; if(w < 0 || !used[w] && DFS(w)){ match[v] = Eiv; match[Eiv] = v; return true; } } return false;}int Bipartite_Matching(){ int ret = 0; memset(match, -1, sizeof(match)); for(int i=0; i
View Code

 

转载于:https://www.cnblogs.com/LiHior/p/8593160.html

你可能感兴趣的文章
网页的居中显示,使用了margin、clear:both
查看>>
用CocoaPods做iOS程序的依赖管理
查看>>
Javaweb小结之——JavaBean+持久层
查看>>
[转]java多线程总结
查看>>
ABAQUS 转子动力学载荷
查看>>
sql语句怎么看效率?
查看>>
CI-微信公众号获取openid和消息推送
查看>>
第一天
查看>>
H5WebSocket前后台代码
查看>>
web学习笔记
查看>>
三个重要属性
查看>>
比较容易理解的iPhone多视图
查看>>
ZOJ1074 最大子矩阵的和
查看>>
关于hadoop中ssh登录的问题
查看>>
Sql中DateTime使用
查看>>
Python logger /logging
查看>>
linux环境下android-ndk下的ffmpeg编译
查看>>
不同的路径12障碍物 · Unique Paths12
查看>>
上海之行(二)迪斯尼
查看>>
一品黄山 天高云淡
查看>>