学习笔记-二分图匹配(匈牙利算法)
2015-11-05 19:46
295 查看
居然在今天才知道二分图匹配也在NOIP范围内,吓死宝宝了,所以晚上弃颓学习了一下
匈牙利算法是利用增广路来求最大匹配的,关于增广路有如下性质:
(1)有奇数条边。
(2)起点在二分图的左半边,终点在右半边。
(3)路径上的点一定是一个在左半边,一个在右半边,交替出现。
(4)整条路径上没有重复的点。
(5)起点和终点都是目前还没有配对的点,而其它所有点都是已经配好对的。
(6)路径上的所有第奇数条边都不在原匹配中,所有第偶数条边都出现在原匹配中。
(7)最后,也是最重要的一条,把增广路径上的所有第奇数条边加入到原匹配中去,并把增广路径中的所有第偶数条边从原
匹配中删除(这个操作称为增广路径的取反),则新的匹配数就比原匹配数增加了1个。
同时从网上了解到有部分题目可以转换求最大匹配来做:
(1)二分图的最小顶点覆盖
最小顶点覆盖要求用最少的点(X或Y中都行),让每条边都至少和其中一个点关联。
Knoig定理:二分图的最小顶点覆盖数等于二分图的最大匹配数。
(2)DAG图的最小路径覆盖
用尽量少的不相交简单路径覆盖有向无环图(DAG)G的所有顶点,这就是DAG图的最小路径覆盖问题。
结论:DAG图的最小路径覆盖数 = 节点数(n)- 最大匹配数(m)
(3)二分图的最大独立集
最大独立集问题: 在N个点的图G中选出m个点,使这m个点两两之间没有边.求m最大值
结论:二分图的最大独立集数 = 节点数(n)— 最大匹配数(m)
PS算法运算过程http://blog.csdn.net/dark_scope/article/details/8880547
模板:
bool find(int x)//调用的函数 { for (int i=1; i<=n; i++)//依次枚举每个点 if (f[x][i]==true && used[i]==false)//f【x】【i】表示二分图中第一个集合里的x点和第二个集合里的i点十分联通 used表示这个点是否被用过 { used[i]=true; if (part[i]==0 || find(part[i])==true)//递归调用判断是否能放 part【i】表示节点i对应的那个点 { part[i]=x; return true; } } return false; }
主程序中调用为:
int ans=0;//匹配数归零 for (int i=1; i<=m; i++) { **memset(used,false,sizeof(used));//注意必须每步都清零,不然会出错** if (find(i)==true) ans++; }
相关文章推荐
- 【大渣】最长上升公共子序列
- linux下创建带密码的用户
- Android基础入门教程——2.2.6 AbsoluteLayout(绝对布局)
- 利用EEPROM实现arduino的断电存储
- JavaScript学习总结(五)原型和原型链详解
- View学习总结
- inline内联函数
- Android基础入门教程——2.2.5 GridLayout(网格布局)
- 【NOIP2015 11.5模拟】总结
- plist
- ubuntu14.04使用root账户登录
- 高级图像处理初步(大米粒的处理)
- Android基础入门教程——2.2.3 TableLayout(表格布局)
- Android基础入门教程——2.2.4 FrameLayout(帧布局)
- Android jdwp 原理
- 2015年11月5日小记
- linux系统启动流程
- NOIP2015模拟11.5总结
- 计算二进制‘1’位数
- Android基础入门教程——2.2.2 RelativeLayout(相对布局)