图论算法》关于匈牙利算法的两三事

摘要:
好了,让我们开始正式介绍匈牙利算法。从1开始,选择1可以连接到的第一条边作为1-C(上图中标记为红色的边)。具体来说,我们从左侧第一个未连接到边的点开始(如原始图所示,它是1),还连接2和第一个未与2连接的点(如上图所示,是A)。

  这是一篇简单的匈牙利算法的理解篇,首先匈牙利算法的名字听起来就和匈牙利牛肉饭一样让人产生食欲(?)233。

  好的接下来我们开始正式带大家了解什么叫匈牙利算法。

  那么要了解算法的基本原理,我们先看一张图

图论算法》关于匈牙利算法的两三事第1张

在这张图里,我们可以清楚的看出图上的点被我们分成了两种,一种是数字,另一种是字母,并且数字与数字、字母与字母之间是没有互相连接的边的,这种点被划为两种、且每种之间没有连边的图就叫做二分图,而我们的匈牙利算法就是用来处理二分图匹配的。

  什么叫二分图匹配捏,很简单,我们从这张图中选出一些边,举个例子,我们选出1——C,2——A,4——D这三条边,使得每条边对应左右两边各一个点,且对于每个点来说,边唯一。

  而对于匈牙利算法来说,它求的是二分图最大匹配,什么叫最大匹配捏,就是说在二分图中选择尽可能多的边,使它们遵从二分图匹配的规则,如果我们选择的边数为全图点数除以2的话,则叫做完全匹配。

  那么匈牙利算法具体怎么实现捏?具体如以下图示

图论算法》关于匈牙利算法的两三事第2张 

首先我们找到左边的1,从1出发选择1能连到的第一条边为1——C(上图中标红的边)

具体为我们从左边第一个没有连到边的点(如原始图所示为1)开始搜索,找到第一个可以连到的点C,然后选择连接两个点,记录连接点C的是1。

图论算法》关于匈牙利算法的两三事第3张

接下来找到第二个点2,同样连接 2 和 与2连接的第一个没有被连接过的点(如上图所示为A),记录连接点A的是2。

  重点!!!!!

  接下来就是匈牙利算法的精髓所在,因为从3开始连接的时候我们就开始慌了,唯一和3连接的点A已经被连过了,那么接下来就是展现匈牙利算法的威力的时刻啦哈哈哈哈哈哈哈(蜜汁笑声)

图论算法》关于匈牙利算法的两三事第4张

  那么我们要做的是用深度优先搜索找出首先找出与当前失匹配点3所能联通的点(上图青色边为我们深搜的过程路径),那么当前所找到的就为A,因为A已经被连接,所以我们可以直接找到连接A的是2,然后继续深搜。

图论算法》关于匈牙利算法的两三事第5张

  然后继续从2开始搜索,找一条能与2连接,并且不是当前来的路径(2——A)的另一条路径(根据匈牙利算法,如果这里找不到就返回上一层,知道搜索完深度优先搜索开始节点3的每一条边,如果都找不到就判断这次算法执行没有更优结果),那么显然的,我们找到了C这个点。

图论算法》关于匈牙利算法的两三事第6张

同样的,我们之前记录过连接C的节点(也就是1),那么继续以1开始搜索与1连接,并且不是1——C这条路径的另一条路径,

图论算法》关于匈牙利算法的两三事第7张

   显然的,找到1——E这条路径,然后对点E进行判断。

图论算法》关于匈牙利算法的两三事第8张

  这时我们发现E是没有其他路径与其他点连接的,那么这时我们开始return,那么看,此时图中所有标为青色的边是我们的搜索路径,那么我们在return时要做的事情就是:把所有{只标青而没有变红的边}变为新的连接边,而吧所有{又标红又标青的边}取消连接.

  那么这时图就变成

图论算法》关于匈牙利算法的两三事第9张

  那么对于当前情况,我们就相当于完成了局部最优匹配,然后接下来就是继续按照这种方法完成全图最优匹配就好了。

   那么完成图就为

图论算法》关于匈牙利算法的两三事第10张

这时我们就求出了二分图最大匹配

(PS写在最后,我们是要记录:{每次连接边后,成功连接右边某个点的左边点的位置},同时如果我们做的找到环的话就只能回到上一层,所以要记录{哪些点在当前搜索中用到(记录一个vis数组)},这样下次搜索就不会死循环)

 然后附上匈牙利算法的模板

 1 bool f(int x)
 2 {
 3     for(int i=head[x];i!=0;i=e[i].next)
 4     {
 5         if(v[i])continue;
 6         v[i]=true;
 7         if(!father[e[i].aim]||f(father[e[i].aim]))
 8         {
 9             father[e[i].aim]=x;
10             return true;
11         }
12     }
13     return false;
14 }

上述模板中判断目标节点是否有父亲和判断目标节点的父亲能否有更优解同时进行。

附上一道大水题 bzoj1191(话说bzoj里有这么水的题真不容易)

题目如下

Description

现在电视台有一种节目叫做超级英雄,大概的流程就是每位选手到台上回答主持人的几个问题,然后根据回答问题的多少获得不同数目的奖品或奖金。主持人问题准备了若干道题目,只有当选手正确回答一道题后,才能进入下一题,否则就被淘汰。为了增加节目的趣味性并适当降低难度,主持人总提供给选手几个“锦囊妙计”,比如求助现场观众,或者去掉若干个错误答案(选择题)等等。 这里,我们把规则稍微改变一下。假设主持人总共有m道题,选手有n种不同的“锦囊妙计”。主持人规定,每道题都可以从两种“锦囊妙计”中选择一种,而每种“锦囊妙计”只能用一次。我们又假设一道题使用了它允许的锦囊妙计后,就一定能正确回答,顺利进入下一题。现在我来到了节目现场,可是我实在是太笨了,以至于一道题也不会做,每道题只好借助使用“锦囊妙计”来通过。如果我事先就知道了每道题能够使用哪两种“锦囊妙计”,那么你能告诉我怎样选择才能通过最多的题数吗?

Input

输入文件的一行是两个正整数n和m(0 < n <1001,0 < m < 1001)表示总共有n中“锦囊妙计”,编号为0~n-1,总共有m个问题。
以下的m行,每行两个数,分别表示第m个问题可以使用的“锦囊妙计”的编号。
注意,每种编号的“锦囊妙计”只能使用一次,同一个问题的两个“锦囊妙计”可能一样。

Output

第一行为最多能通过的题数p

Sample Input

5 6
3 2
2 0
0 3
0 4
3 2
3 2

Sample Output

4

 没什么好讲的,最裸的匈牙利,愉快的贴出代码

图论算法》关于匈牙利算法的两三事第11张图论算法》关于匈牙利算法的两三事第12张
 1 #include<cstdio>
 2 #include<cstring>
 3 struct shit{int aim,next;}e[2200];
 4 int father[2200],a,b,n,m,point,head[2200];
 5 bool v[2200];
 6 void  fuck(int x,int y)
 7 {
 8     e[++point].aim=y;
 9     e[point].next=head[x];
10     head[x]=point;
11 }
12 bool f(int x)
13 {
14     for(int i=head[x];i!=0;i=e[i].next)
15     {
16         if(v[i])continue;
17         v[i]=true;
18         if(!father[e[i].aim]||f(father[e[i].aim]))
19         {
20             father[e[i].aim]=x;
21             return true;
22         }
23     }
24     return false ;
25     
26 }
27 int main()
28 {
29     scanf("%d%d",&n,&m);
30     for(int i=1;i<=m;i++)
31     {
32         scanf("%d%d",&a,&b);
33         fuck(i,a),fuck(i,b);
34     }
35     int k;
36     for(k=1;k<=m;k++)
37     {
38         memset(v,0,sizeof(v));
39         if(!f(k))break;
40     }
41     printf("%d",k-1);
42     return 0;
43 }
View Code

免责声明:文章转载自《图论算法》关于匈牙利算法的两三事》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇div学习之div中dl-dt-dd的详解[转] SSH两种登录方式(公私钥)解析下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

TensorFlow 2.0 深度学习实战 —— 浅谈卷积神经网络 CNN

前言 上一章为大家介绍过深度学习的基础和多层感知机 MLP 的应用,本章开始将深入讲解卷积神经网络的实用场景。卷积神经网络 CNN(Convolutional Neural Networks,ConvNet)是一种特殊的深度学习神经网络,近年来在物体识别、图像重绘、视频分析等多个层面得到了广泛的应用。本文将以VGG16预训练模型为例子,从人脸识别、预训练模...

【推荐系统实战】:C++实现基于用户的协同过滤(UserCollaborativeFilter)

好早的时候就打算写这篇文章,可是还是參加阿里大数据竞赛的第一季三月份的时候实验就完毕了。硬生生是拖到了十一假期。自己也是醉了。。。 找工作不是非常顺利,希望写点东西回想一下知识。然后再攒点人品吧,仅仅能如此了。 一、问题背景 二、基于用户的协同过滤算法介绍 三、数据结构和实验过程设计 四、代码 一、问题背景 首先介绍一下问题的背景。如今我有四个月的用户...

MPI编程简单介绍

第三章 MPI编程   3.1 MPI简单介绍 多线程是一种便捷的模型,当中每一个线程都能够訪问其他线程的存储空间。因此,这样的模型仅仅能在共享存储系统之间移植。一般来讲,并行机不一定在各处理器之间共享存储,当面向非共享存储系统开发并行程序时,程序的各部分之间通过来回传递消息的方式通信。要使得消息传递方式可移植,就须要採用标准的消息传递库。这就促成的消...

字符串匹配算法

一、简介 文本信息可以说是迄今为止最主要的一种信息交换手段,而作为文本处理中的一个重要领域——字符串匹配,就是我们今天要说的话题。(原文还特意提及文本数据数量每18个月翻一番,以此论证算法必须要是高效的。不过我注意到摩尔定律也是18个月翻番,这正说明数据的增长是紧紧跟随处理速度的,因此越是使用高效的算法,将来待处理的数据就会越多。这也提示屏幕前的各位,代码...

[PHP] 6种负载均衡算法

CP from : https://www.cnblogs.com/SmartLee/p/5161415.html http://www.dataguru.cn/thread-559329-1-1.html 1、轮询法 将请求按顺序轮流地分配到后端服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载。 2、随机法 通过...

unity sprite怎么获取切割后的图

学习了一段时间的unity,对里面的组件有一个大致的了解,但是具体操作来说还不是很熟悉,今天看了一片关于unity sprite怎么获取切割后的图的文章,感觉还不错。 假设有一张png/tga图集,导入到Unity,放置目录"Assets/Resources/UI"(UI文件夹可替换成其他的,重要的是要在"Assets/Resources/"路径下),默认...