最近开始学习图论的二分匹配,关于最大匹配做一次小总结,希望自己后面回头来看一目明了,也对刚接触的人有帮助:

ps:开始有的文字很多....对于很多人来说一看到文字就烦啦...不过这个总结是针对匈牙利算法的总结,后面的匈牙利代码中有详细说明并结合图片说明,相信对刚接触的人会有帮助

个人觉得对于一个知识点最好是先知道这个”东东“是什么,然后在学习概念比较好,关于先知道是个什么“东东”--就是把这个知识点简单明了化,然后去了解其中令人头疼的概念!

关于二分匹配的最大匹配:

如果有G1、G2、G3三个女孩,B1。B2。B3三个男孩,有一天老师说要调整座位,就了解三个女孩的想法(想和哪一个男孩坐在一起----男孩的想法不考虑),G1说和三个男孩任何一个坐一起都喜欢,G2就说只想和B1坐一起,G3只想和 B2坐一起,那么老师改怎么安排座位,让尽可能多的女孩满意?这里就引入匹配:结合图形理解:

可以看到让G1和B3坐一起(配对/匹配)G2和B1一起,G3和B2一起,那么三个人都会满意,如果换成其他的方案,就不会是三个女孩都满意啦...那么这就是最大匹配

--------------------------------------------------------------------------------------------------------------------------------------------------------在大概了解了最大匹配是什么东东之后,就有必要了解一些概念啦,推荐:基本概念术语

下面是关于求最大匹配的匈牙利算法:

令G = (X,*,Y)是一个二分图,其中,X = {x1,x2,...xm}, Y = {y1,y2,...yn}。令M为G中的任一个匹配。
1)讲X的所有不与M的边关联的顶点标上(@),并称所有的顶点为未被扫描的。转到 2)。
2)如果在上一步没有新的标记加到X的顶点上,则停止。否则转到 3)。
3)当存在X被标记但未被扫描的顶点时,选择一个被标记但未被扫描的X的顶点,比如,xi,用(xi)标记Y的所有顶点,这些顶点被不属于M且尚未标记的边连到xi .现在,顶点xi是被扫描的。如果不存在被标记但未被扫描的顶点,则转到 4)。
4)如果在步骤 3)没有新的标记被标到Y的顶点上,则停止。否则,转到 5)。
5)当存在Y被标记但未被扫描的顶点时,选择Y的一个被标记但未被扫描的顶点,比如yi,用(yi)标记X的顶点,这些顶点被属于M且尚未标记的边连到yi.现在,顶点yi是被扫描的。如果不存在被标记但未被扫描的顶点,则转到 2)。
也可以叙述为:
[ZZ]匈牙利算法
关键在于匈牙利算法的递归过程中有很多重复计算的节点,而且这种重复无法避免,他不能向动态规划一样找到一个“序”将递归改为递推

下面结合hdu2063模板详细解释匈牙利算法:

题目和上面的座位匹配差不多

// 1216k 15ms
#include<stdio.h>
#include<string.h> #define MAX 501 int map[MAX][MAX];//map[i][j]=1表示i想和j一起,为0就是没有想一起的想法
int link[MAX];//link[i]=t就表示和i配对/匹配的是t!这里注意i表示是i号男生和t号女生配对
int useif[MAX];//useif[i]只有1和0两个值,表示i是不是当前考虑要匹配的,为1就是当前考虑i要匹配
//看了几个定义之后就从main函数中开始看
int n,m,k;

bool dfs(int t)
{
for(int i=1;i<=n;i++)//这里对于女孩t,考虑每一个男生能否和t匹配
{
if(!useif[i] && map[t][i])//i号男生没有被考虑,并且t想和i一起
{
useif[i]=1;//标记考虑
if(link[i] == -1 || dfs(link[i]))//如果i没有匹配的女生(link[i]=-1)或者--这个在开始有点难理解,后面给出一段话结合图片有助理解,这里只要明白这语句的意思是:if(t能和i匹配)
{
link[i]=t; return true;//能匹配就把link[i]更新为t,返回true
}
}
}
return false;
} int match()
{
int sum=0;
memset(link,-1,sizeof(link));//匹配之前,每个人(题目中是男孩)匹配为-1
for(int i=1;i<=m;i++)//这里,对于每一个女孩i,去选一个男孩匹配
{
memset(useif,0,sizeof(useif));//初始化对于女孩i,没有考虑任何男生
if(dfs(i))//看i能不能从男生中选一个匹配,调用dfs
sum++;//能匹配就产生一对啦....就加一
}
return sum;//返回能产生的对数
} int main()
{
while(scanf("%d",&k),k)
{
scanf("%d%d",&m,&n);
int i,j;
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
map[i][j]=0;//初始化都没有想法
int a,b;
for(i=0;i<k;i++)
{
scanf("%d%d",&a,&b);//对于每个a想和b一起就赋值map[a][b]=1
map[a][b]=1;
}
printf("%d\n",match());//开始match匹配,调用match
}
return 0;
}

这里对于上面的if加以说明:

拿案例来说(左边的是女生的标号,右边是等待女生选择的男生标号)

1   1
1    2

1   3

2   1

2   3

3   1

最开始我们用女孩一号去匹配得到如下图:

然后我们对于G2去选择,此时我们依旧从1号男生开始考虑,因为useif[1]在女孩2开始匹配的时候初始化为0啦,并且女孩2也想和男孩1匹配,就标记useif[1]为正在考虑,然后发现link[1]=1(也就是1号男生被1号女生选走啦)但是,确定是否2号女孩能和1号男孩匹配的还有一个条件,就是dfs(link[1]),意思是看能不能把和1号男生匹配的1号女生再去选择另一个男生配对,那么这个函数调用,我们的女1号就选择的2号男生,所以,这里的2号女生就可以和1号男生在一起啦...(有图有真相):

-----那么,后面就是一样的啦...

二分匹配之最大匹配学习总结完毕.......

[置顶] 白话二分匹配之最大匹配+附上hdu2063解题报告的更多相关文章

  1. [置顶] 白话最小边覆盖总结--附加 hdu1151结题报告

    刚开始看到这个题目的时候就觉得想法很明了,就是不知道如何去匹配... 去网上看了不少人的解题报告,但是对于刚接触“最小边覆盖”的我来说....还是很困难滴....于是自己又开始一如以往学习“最大独立集 ...

  2. 欧几里德&扩展以及求解线性方程学习总结--附上poj1061解题报告

    欧几里德算法: 欧几里德就是辗转相除法,调用这个gcd(a,b)这个函数求解a,b的最大公约数 公式: gcd(a,b)=gcd(b,a%b):并且gcd(a,b)=gcd(b,a)=gcd(-a,b ...

  3. UVALive - 7427 the math 【二分匹配】

    题目链接 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...

  4. 【HDU 2255】奔小康赚大钱 (最佳二分匹配KM算法)

    奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  5. [置顶] Android开发笔记(成长轨迹)

    分类: 开发学习笔记2013-06-21 09:44 26043人阅读 评论(5) 收藏 Android开发笔记 1.控制台输出:called unimplemented OpenGL ES API ...

  6. [kuangbin带你飞]专题十 匹配问题 二分匹配部分

    刚回到家 开了二分匹配专题 手握xyl模板 奋力写写写 终于写完了一群模板题 A hdu1045 对这个图进行 行列的重写 给每个位置赋予新的行列 使不能相互打到的位置 拥有不同的行与列 然后左行右列 ...

  7. BZOJ 1189 二分匹配 || 最大流

    1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1155  Solved: 420[Submi ...

  8. Kingdom of Obsession---hdu5943(二分匹配)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5943 题意:给你两个数n, s 然后让你判断是否存在(s+1, s+2, s+3, ... , s+n ...

  9. [ACM_图论] Sorting Slides(挑选幻灯片,二分匹配,中等)

    Description Professor Clumsey is going to give an important talk this afternoon. Unfortunately, he i ...

随机推荐

  1. Java基础知识强化92:日期工具类的编写和测试案例

    1. DateUtil.java,代码如下: package cn.itcast_04; import java.text.ParseException; import java.text.Simpl ...

  2. css实现鼠标移上去变大,旋转,转别人的额

    <!doctype html><html><head> <meta charset="utf-8"> <title>CS ...

  3. Android开发手记(7) 按钮类控件的使用

    1.点击Button改变页面背景色 通过Button改变页面背景色,首先新建相应的对象,让后绑定到Layout上的元素. final RelativeLayout layout = (Relative ...

  4. Sql 中常用日期转换Convert(Datetime)

    CONVERT(data_type,expression[,style]) convert(varchar(10),字段名,转换格式) 说明:此样式一般在时间类型(datetime,smalldate ...

  5. Arcgis server - ' packaging failed '

    我在使用ARCCatalog发布地图服务时,报这个错:packaging failed 然后我从头试,发现它提示说我的目录'C:\Users\Administrator\AppData\Local\E ...

  6. ASP.NET 页面间数据传递的方法

    在做WEB开发时,很多地方会涉及到页面间的数据传递.这几天在完善教务基础系统,遇到了这个问题,上网查了一些资料,现总结如下: 说到页面间数据传递,很多人都会想到通过像Session这样的全局变量,但是 ...

  7. 传输层-TCP

    UDP协议提供了端到端之间的通讯,应用程序只需要在系统中监听一个端口,便可以进行网络通讯.随着计算机网络的发展,计算机网络所承载的业务越来越多,有些业务数据的传输需要具备可靠性,譬如我们在进行在线聊天 ...

  8. JavaScript 客户端JavaScript之Document对象中的表单和表单元素

    Form对象 代表一个HTML表单(document可以有多个表单元素) 表单访问 document.form[document.forms.length-1] 访问表单元素 document.for ...

  9. 【转】windows消息16进制对应表

    来源:http://blog.sina.com.cn/s/blog_962250db0101d4mj.html windows mobile编程,无论使用eVC还是.net CF,都脱不开window ...

  10. Something About Variable

    CONTENT(目录)    前言      Variable declearation:three rules you can break          1.Don't set var stat ...