二分图匹配-匈牙利算法学习心得

本文探讨了二分图的概念,即图的左右两部分通过边相连但内部无边。二分图匹配问题,例如情侣配对,可以通过匈牙利算法来解决。匈牙利算法基于网络流思想,主要寻找增广路,当无法找到增广路时,当前匹配数即为最大匹配数。在实现过程中,使用For数组记录匹配状态,used数组标记已尝试节点,避免重复搜索。通过代码实例展示了匈牙利算法在飞行员配对方案问题的应用。

什么叫二分图呢。。。

就是这样的。。。

通俗地讲 就是一个图有左右两部分 左右部分没有边 但是他们左右相连了

什么又叫匹配呢。。。比如就是这样一道题


现在你要使得情侣尽可能的多 这就叫二分图的匹配。。

匈牙利算法就是解决二分图匹配的经典算法

匈牙利算法其实就是一种网络流的思想 本质就是不断地寻找增广路,当找不到增广路的时候,当前增广路数量就是答案

定义数组:For 表示当前点已经匹配的点    used 标记数组 表示该点已经试图被查过了 如果查过(且used[i]=1 ) 就不必浪费功夫再查一遍(值得一提的是 used数组每次查询都要初始化为0)

查询过程:遍历左部分(右也行...)对于每一个点 从这个点出发,向它每一个相连的点遍历过去。如果这个点没有被查过,且这个点名花无主或者它的原本匹配点可以找到别人,那么就把这个点与出发点匹配

看代码吧(网络流24题第一题 飞行员配对方案问题)

//匈牙利算法的本质就是不断地寻找增广路,当找不到增广路的时候,当前增广路数量就是答案
#include<bits/stdc++.h>
using namespace std;
int tot,ans,m,n,x,y,used[505],For[505],first[505];
struct Edge
{
	int next;
	int to;
}edge[1000005];
inline void addedge(int x,int y)
{
	edge[tot].to=y;
	edge[tot].next=first[x];
	first[x]=tot++;
}
inline void init()
{
	memset(first,-1,sizeof(first));
	for(int i=0;i<=1000004;i++)	edge[i].next=-1;
}
bool find(int x)
{
	for(int u=first[x];u!=-1;u=edge[u].next)
	{
		int vis=edge[u].to;
		if(used[vis]==0)	//如果没标记过  
		{
			used[vis]=1;
			if(find(For[vis])||For[vis]==0)	//名花无主或者可以另寻他主 
			{
				For[vis]=x;
				return true;
			}
		}
	}
	return false;
}
int main()
{
//	freopen("input.in","r",stdin); 
	cin>>m>>n;
	init();
	while(cin>>x>>y)
	{
		if(x==-1&&y==-1)	break;
		addedge(x,y);
	}
	for(int i=1;i<=m;i++)
	{
		memset(used,0,sizeof(used));
		if(find(i))	ans++;
	}
	cout<<ans<<endl;
	for(int i=1;i<=n;i++)
	{
		if(For[i]!=0)	cout<<For[i]<<" "<<i<<endl;
	}
	return 0;
}
行了。。。就讲到这儿吧
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值