二分匹配之匈牙利算法

  匈牙利算法的原理为:从当前匹配M出发(如果没有匹配,则取初始匹配M = φ),检查没一个未盖点,然后从它出发寻找可增广路,找到可增广路,则沿着这条可增广路进行扩充,知道不存在增广路为止。

  根据从未盖点出发寻找增广路搜索的办法,可以分为:1、DFS增广。 2、BFS增广。

在算法中用到的一些变量定义以及预处理如下:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib> 
using namespace std;

#define MAXN 110
#define MAXM 10010

int G[MAXN][MAXN];

int xlink[MAXN]; //表示最终求得的最大匹配中与Xi匹配的Y顶点,ylink同理。
int ylink[MAXN];
bool vis[MAXN]; //DFS中记录顶点访问状态,0表示未访问过,1表示访问过 

int nx, ny; //X、Y集合顶点的个数 

inline void init()
{
	memset(G, 0, sizeof(G));
	memset(xlink, -1, sizeof(xlink));
	memset(ylink, -1, sizeof(ylink)); //初始化为-1 
}

匈牙利算法:

bool ED(int u)
{
	      //看题目具体的下标 
	for(int v = 1; v <= ny; v++) if(G[u][v]) 
	{
		if(!vis[v]) //v与u邻接,且从来没有访问过。 
		{
			vis[v] = 1; //访问v
			if(ylink[v] == -1 || ED(ylink[v])) 
			{ //如果v没有匹配,或者v已经匹配了,但可以从ylink[v]出发找到一条增广路
			//注意如果前一个条件成立,就不会递归。 
				xlink[u] = v; //把v匹配给u 
				ylink[v] = u; //把u匹配给v 
				return true; //找到可增广路 
			} 
		}
	}
	return false; //不存在从u开始的增广路 
}

int MaxMatch()
{
	int ans = 0;
	for(int i = 1; i <= nx; i++)
	{
		if(xlink[i] == -1) //从每个未盖点出发进行寻找增广路
		{
			memset(vis, 0, sizeof(vis));
			ans += ED(i);
		}
	}
	return ans;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值