匈牙利算法

匈牙利算法是一种用于计算最大匹配的算法

......

什么是匹配呢,简单来说就是两点一线。例如一个选手匹配一台计算机。这两个点分别来自两个不同集合

假如现在给你N个选手,M台机子,每个选手有他讨厌的机子,问最多能满足多少个选手的喜好,这就是一个典型的最大匹配问题

最大匹配问题可以用网络流解决,用一个超级源点接上一个集合的所有点,边上容量为1;

一个超级汇点接上另一个集合的所有点,边的容量也为1。跑一遍最大流就好啦。

但是我们发现这个网络流有特殊型:边的容量都为1;有没有更简便的算法呢,匈牙利算法便诞生啦。

首先一个点要找到匹配它的点,必须满足 1  它们有边连接 2 这个点没有被匹配,或是在不减少匹配数的前提下能把它空出来 。

那么重要的就是把这个点空出来了。下面结合代码解释。

int link[17005],vis[17005];//link[i]表示i的匹配对象,vis[i]表示i是否访问过。
int find(int x)//询问x是否能找到匹配对象 
{
	for(int k=head[x];k;k=nxt[k])//遍历x的边  
	{
		int v=des[k];//v为我们的候选对象 
		if(!vis[v])//v必须没有被我们访问过 
		{
			vis[v]=1;
			if(link[v]==0||find(link[v]))//v没有被匹配或是v现在匹配的对象能找到新对象 
			{
				link[v]=x;//v与x匹配。 
				return 1;//匹配成功。 
			}
		}
	}
	return 0;//否则匹配失败 
}//注意每次进入函数前需清零vis[]数组

用匈牙利算法其实最重要的是搞清楚那两个集合与边的意义。

一般符合的题意性质有:

(1) 选了这个,就不能选与之相连的那个

(2) 任选了一条路径的两个端点之一都算是选了这条边

这里再贴一道题:有N个障碍分布在一个K*M的矩阵里,给出每个障碍的坐标。一次可以消除一行或一列的障碍。问最小消除多少次能消掉所有障碍(N,K,M<=10000)。

其实最大匹配有各种应用,这里再贴道题吧。poj3020天线放置。(比较难了)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值