二分图学习小结
来源:互联网 发布:程序员的自我修养txt 编辑:程序博客网 时间:2024/06/08 05:45
匹配: 在图论中,一个匹配是一个边的集合,其中任意两条边都没有公共顶点。
最大匹配: 一个图所有匹配中,所含匹配边数最多的匹配,称为这个图的最大匹配
最大匹配数:最大匹配的匹配边的数目
完美匹配:如果一个图的某个匹配中,所有的顶点都是匹配点,那么它就是一个完美匹配。
最小点覆盖数:选取最少的点,使任意一条边至少有一个端点被选择
最大独立数:选取最多的点,使任意所选两点均不相连
最小路径覆盖数:对于一个 DAG(有向无环图),选取最少条路径,
使得每个顶点属于且仅属于一条路径。路径长可以为 0(即单个点)。
定理1:最大匹配数 = 最小点覆盖数(这是 Konig 定理)
定理2:二分图最大独立集=顶点数-二分图最大匹配
定理3:最小路径覆盖数 = 顶点数 -最大匹配数二分图中的增广路径的性质:
(1)有奇数条边。
(2)起点在二分图的左半边,终点在右半边。
(3)路径上的点一定是一个在左半边,一个在右半边,交替出现。(其实二分图的性质就决定了这一点,因为二分图同一边的点之间没有边相连,不要忘记哦。)
(4)整条路径上没有重复的点。
(5)起点和终点都是目前还没有配对的点,而其它所有点都是已经配好对的。
(6)路径上的所有第奇数条边都不在原匹配中,所有第偶数条边都出现在原匹配中。
(7)最后,也是最重要的一条,把增广路径上的所有第奇数条边加入到原匹配中去,并把增广路径中的所有第偶数条边从原匹配中删除(这个操作称为增广路径的取反),则新的匹配数就比原匹配数增加了1个。学习资料:http://blog.csdn.net/xuguangsoft/article/details/7861988
关键是建图:建立A,B两个集合,集合内是没有关系的,集合之间是单向关系
二分图的性质:在无向图G中,至少要有两个点。如果存在回路,那么回路必为偶数边的回路。。
多重匹配:一对多的二分图的多重匹配。二分图的多重匹配算法的实现类似于匈牙利算法,对于集合X中的元素xi,找到一个与其相连的元素yi后,检查匈牙利算法的两个条件是否成立,若yi未被匹配,则将xi,yi匹配。否则,如果与yi匹配的元素已经达到上限,那么在所有与yi匹配的元素中选择一个元素,检查是否能找到一条增广路径,如果能,则让出位置,让xi与yi匹配。
match[i][j]表示X集合中的Xi点与y集合中的j个点相连接(一对多)
- 匈牙利算法模板
//二分图匹配(匈牙利算法的DFS实现)//初始化:g[][]两边顶点的划分情况//建立g[i][j]表示i->j的有向边就可以了,是左边向右边的匹配//g没有边相连则初始化为0,邻接表表示则清空//Nx是匹配左边的顶点数,Ny是匹配右边的顶点数//调用:res=hungary();输出最大匹配数//优点:适用于稠密图,DFS找增广路,实现简洁易于理解//时间复杂度:O(VE)//顶点编号从0开始的#define cl(a,b) memset(a,b,sizeof(a));const int maxn=222;vector<int> G[maxn];int matching[maxn];bool vis[maxn];int Nx,Ny;//左右节点数bool dfs(int u){ int N=G[u].size(); for(int i=0;i<N;i++){ int v=G[u][i]; if(vis[v])continue; vis[v]=true; if(matching[v]==-1||dfs(matching[v])){ matching[v]=u; return true; } } return false;}int hungar(){ int ans=0; cl(matching,-1); for(int i=0;i<Nx;i++){ cl(vis,false); if(dfs(i))ans++; } return ans;}
2 Hopcroft-Karp算法模板
这个算法比匈牙利算法的时间复杂度要小,大数据可以采用这个算法是对匈牙利算法的优化,每次找到多条可以增广的路径集合二分图匹配(Hopcroft-Karp的算法)。初始化:g[][]邻接矩阵,但是我喜欢邻接表,使用前清空调用:res=MaxMatch(); 邻接矩阵 Nx,Ny要初始化,邻接表的话,只要初始化Nx时间复杂大为 O(V^0.5 E)适用于数据较大的二分匹配const int maxn=3005;const int inf=999999;vector<int> G[maxn];int mx[maxn],my[maxn],dx[maxn],dy[maxn];bool vis[maxn];int Nx,Ny,dis;bool bfs(){ queue<int> q; cl(dx,-1); cl(dy,-1); dis=inf; for(int i=0;i<Nx;i++){ if(mx[i]==-1){ q.push(i); dx[i]=0; } } while(!q.empty()){ int u=q.front();q.pop(); if(dx[u]>dis)break; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(dy[v]==-1){ dy[v]=dx[u]+1; if(my[v]==-1)dis=dy[v];//表示找到一条增广路了,更新最小距离 else { dx[my[v]]=dy[v]+1; q.push(my[v]); } } } } return dis!=inf;}bool dfs(int u){ int N=G[u].size(); for(int i=0;i<N;i++){ int v=G[u][i]; if(!vis[v]&&dy[v]==dx[u]+1){ vis[v]=true; if(my[v]!=-1&&dy[v]==dis)continue; if(my[v]==-1||dfs(my[v])){ my[v]=u; mx[u]=v; return true; } } } return false;}int Maxmatch(){ int ans=0; cl(mx,-1); cl(my,-1); while(bfs()){ cl(vis,false); for(int i=0;i<Nx;i++){ if(mx[i]==-1&&dfs(i))ans++; } } return ans;}
部分类型题目:
1.最大匹配
2.最小路径覆盖
3.最小点覆盖
4.最大独立集
5.行列匹配奇偶匹配,染色,缩点,
6.路径输出解答输出
7.建图细节反向建图,极大完全子图,
8.一对多匹配 , 多对多匹配
9.二分答案+匹配
10.二分图性质应用
未完待续 。。。
- 二分图学习小结
- 二分图小结
- 二分图小结
- 二分图小结
- 二分图小结-poj.3020
- 二分图最大匹配小结
- 二分图相关问题小结
- 二分小结
- 二分 小结
- 二分小结
- 二分小结
- 二分图最小点覆盖小结
- 二分图的匹配算法小结
- 二分图学习笔记
- 二分图学习
- 二分图学习整理
- 二分图学习
- 二分图 学习笔记
- 小白学开发(iOS)OC_基本数据类型转换成字符串(2015-08-12)
- leetcode 139 —— Word Break
- centos6.7源码安装mysql
- 小白学开发(iOS)OC_ 字符串重组(2015-08-13)
- OC - NSSetAndNSMutableSet
- 二分图学习小结
- Adapter的The content of the adapter has changed问题分析
- 注册表常识1
- 策略模式
- 小白学开发(iOS)OC_ 字符串写入文件(2015-08-13)
- 设计模式之代理模式
- jeecms标签对应的类,方便查找标签的输入输出参数,以及参数对应的数值类型、范围
- 关于Qt中自定义槽和信号的简单示例
- 小白学开发(iOS)OC_ 从文件中读取字符串内容(2015-08-14)