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

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. 【JavaScript】深入分析JavaScript的关系运算和if语句

    JavaScript的关系运算,没有我原想的那么简单.等终于理清它的运算逻辑之后,我的头大了至少一圈.而if语句的真假判定逻辑本身不难,但要把它和关系运算联系起来,相信你会和我一样,到达崩溃边缘.不信 ...

  2. [转] java中注解的使用与实例

    注解目前非常的流行,很多主流框架都支持注解,而且自己编写代码的时候也会尽量的去用注解,一时方便,而是代码更加简洁. 注解的语法比较简单,除了@符号的使用之外,它基本与Java固有语法一致.Java S ...

  3. 【酷Q插件制作】教大家做一个简单的签到插件

    酷Q插件已经有很多了,社区分享一大堆,不过还是自己写才有乐趣,哈哈.不得不吐槽一下,酷Q竟然不更新了,出了个酷Q pro,还收费!!诶.不过这也影响不了咱写插件的心情,今天教大家写一个酷Q签到插件,虽 ...

  4. RSA 非对称加密 数字签名 数字证书

    什么是RSA加密算法 RSA加密算法是一种非对称加密算法,算法的数学基础是极大数分解难题. RSA加密算法的强度也就是极大数分解的难度,目前700多位(二进制)的数字已经可以破解,1024位认为是比较 ...

  5. Java基础知识强化100:jsp和servlet有什么区别

         首先你先要弄懂什么是servlet,servlet是在服务器端执行的java程序,只不过它有专门的一套规则(就是我们平常所说的api):jsp说得简单点就是用另一套简单的规则写的servle ...

  6. 配置ISCSI服务器

    一.在linux下安装启动iscsi target 1.安装启动iscsi服务 [root@wjb10000 ~]# yum -y install targetcli.noarch 2.建立一个目录设 ...

  7. 在linux后台执行脚本

    1. 使用&符号在后台执行命令 你可以在Linux命令或者脚本后面增加&符号,从而使命令或脚本在后台执行,例如:. $ ./my-shell-script.sh & 2. 使用 ...

  8. C#Linq的使用

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  9. 【转载】经典10道c/c++语言经典笔试题(含全部所有参考答案)

    经典10道c/c++语言经典笔试题(含全部所有参考答案) 1. 下面这段代码的输出是多少(在32位机上). char *p; char *q[20]; char *m[20][20]; int (*n ...

  10. PHPCMSV9 采集网址后,再采集内容,报错:“采集采集内容 没有找到网址列表,请先进行网址采集”

    解决方法:直接清除v9_collection_history 表里的内容.