匈利亚算法实现

简介: 匈利亚算法实现

导读:什么是最大匹配?

要了解匈牙利算法必须先理解下面的概念:

匹配:在图论中,一个「匹配」是一个边的集合,其中任意两条边都没有公共顶点。

最大匹配:一个图所有匹配中,所含匹配边数最多的匹配,称为这个图的最大匹配。

下面是一些补充概念:

完美匹配:如果一个图的某个匹配中,所有的顶点都是匹配点,那么它就是一个完美匹配。

交替路:从一个未匹配点出发,依次经过非匹配边、匹配边、非匹配边…形成的路径叫交替路。

增广路:从一个未匹配点出发,走交替路,如果途径另一个未匹配点(出发的点不算),则这条交替 路称为增广路(agumenting path)。

匈牙利算法

不讲算法证明(我也不会)。

用一个转载的例子来讲解匈牙利算法的流程。

代码实现匈牙利算法

首先是存图模板

//邻接表写法,存稀疏图
int h[N],ne[N],e[N],idx;
//n1,n2分别是两个点集的点的个数
int n1,n2,m;
void add(int a , int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void init()
{
memset(h,-1,sizeof h);
}
//存边只存一边就行了,虽然是无向图。
for(int i = 0 ; i < n1 ; i ++)
{
int a,b;
cin>>a>>b;
add(a,b);
}

接下来看算法模板(c++)

//match[j]=a,表示女孩j的现有配对男友是a
int match[N];
//st[]数组我称为临时预定数组,st[j]=a表示一轮模拟匹配中,女孩j被男孩a预定了。
int st[N];
//这个函数的作用是用来判断,如果加入x来参与模拟配对,会不会使匹配数增多
int find(int x)
{
//遍历自己喜欢的女孩
for(int i = h[x] ; i != -1 ;i = ne[i])
{
int j = e[i];
if(!st[j])//如果在这一轮模拟匹配中,这个女孩尚未被预定
{
st[j] = true;//那x就预定这个女孩了
//如果女孩j没有男朋友,或者她原来的男朋友能够预定其它喜欢的女孩。配对成功,更新match
if(!match[j]||find(match[j]))
{
match[j] = x;
return true;
}
}
}
//自己中意的全部都被预定了。配对失败。
return false;
}
//记录最大匹配
int res = 0;
for(int i = 1; i <= n1 ;i ++)
{
//因为每次模拟匹配的预定情况都是不一样的所以每轮模拟都要初始化
memset(st,false,sizeof st);
if(find(i))
res++;
}

下面用一个gif动图来演示这个整个配对的递归过程:

练习例题: 二分图的最大匹配

AC代码

#include
#include
using namespace std;
const int N = 510 , M = 100010;
int n1,n2,m;
int h[N],ne[M],e[M],idx;
bool st[N];
int match[N];
void add(int a , int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void init()
{
memset(h,-1,sizeof h);
}
int find(int x)
{
//遍历自己喜欢的女孩
for(int i = h[x] ; i != -1 ;i = ne[i])
{
int j = e[i];
if(!st[j])//如果在这一轮模拟匹配中,这个女孩尚未被预定
{
st[j] = true;//那x就预定这个女孩了
//如果女孩j没有男朋友,或者她原来的男朋友能够预定其它喜欢的女孩。配对成功
if(!match[j]||find(match[j]))
{
match[j] = x;
return true;
}
}
}
//自己中意的全部都被预定了。配对失败。
return false;
}
int main()
{
init();
cin>>n1>>n2>>m;
while(m–)
{
int a,b;
cin>>a>>b;
add(a,b);
}
int res = 0;
for(int i = 1; i <= n1 ;i ++)
{  
     //因为每次模拟匹配的预定情况都是不一样的所以每轮模拟都要初始化
      memset(st,false,sizeof st);
    if(find(i)) 
      res++;
}  
cout<<res<<endl;

}


相关文章
|
15小时前
|
传感器 编解码 算法
常见的电机控制算法实现
常见的电机控制算法实现
30 0
常见的电机控制算法实现
|
算法
算法练习——(2)逢7过
中国朋友们聚会时喜欢玩"逢7过"的游戏,老外有个同样的游戏,FlipFlop,它从1计数到100,顺序输出。当遇到3的倍数就要说“Flip”,遇到5的倍数就要说“Flop”,既为3的倍数又为5的倍数则要说“FlipFlop”,说错的话表演节目或罚酒。
145 0
|
算法 索引
紫书之子集生成三种算法
紫书之子集生成三种算法
紫书之子集生成三种算法
|
算法 Java 索引
插值查找算法
插值查找算法又称插值搜索算法,是在二分查找算法的基础上改进得到的一种查找算法。
253 0
|
算法 Java C++
算法题0
第一题:判断数字 给定一个整数 n,请你统计其各位数字中 4 和 7 的出现次数。 如果 4 的出现次数加上 7 的出现次数恰好等于 4 或 7,则输出 YES,否则输出 NO。 例如,当 n=40047 时,4 出现了 2 次,7 出现了 1 次,2+1=3,既不是 4 也不是 7,因此,输出 NO;当 n=7747774 时,4 出现了 2 次,7 出现了 5 次,2+5=7,因此,输出 YES。
134 0
|
算法
【算法之初步认识】
【算法之初步认识】
118 0
【算法之初步认识】
|
人工智能 算法
什么是算法?
当人们提到“算法”一词,往往就会把它们当成专属于“人工智能”的范畴,很多专业的计算机人士也是,提起算法就头疼,不知道如何学习算法,慢慢的对算法就会失去兴趣,算法不仅仅是计算机行业特有的,在我们的生活中也处处存在着算法,算法是专注于解决问题的过程和方法。
156 1
什么是算法?
|
算法 JavaScript
算法总结
猫狗队列 注意: 查找了一些网上的写法,发现很多样本再处理pollAll pollDog pollCat方法的时候,并不是如下边的要求弹出所有,原因不详,以我对文字的 敏感性来说,这种只弹出一个的方式是错误的,奈何很多公司的算法题 答案也是如此,所以暂且先这样处理,你完全可以添加一个循环将所有 元.
1317 0
|
算法
算法技巧总结
算法技巧总结
1353 0
|
算法 C++ 编译器