二分图匹配,匈牙利算法详解

博文转自(http://blog.csdn.net/akof1314/article/details/4421262)

这是一种用增广路求二分图最大匹配的算法。它由匈牙利数学家Edmonds于1965年提出,因而得名。 定义 未盖点:设Vi是图G的一个顶点,如果Vi 不与任意一条属于匹配M的边相关联,就称Vi 是一个未盖点。

二分图匹配,匈牙利算法详解_第1张图片

 

交错路:设P是图G的一条路,如果P的任意两条相邻的边一定是一条属于M而另一条不属于M,就称P是一条交错路。

可增广路:两个端点都是未盖点的交错路叫做可增广路。

二分图匹配,匈牙利算法详解_第2张图片

 

二分图匹配,匈牙利算法详解_第3张图片

 

流程图

二分图匹配,匈牙利算法详解_第4张图片

bool 寻找从k出发的对应项出的可增广路
{
	while (从邻接表中列举k能关联到顶点j)
	{
		if (j不在增广路上)
		{
			把j加入增广路;
			if (j是未盖点 或者 从j的对应项出发有可增广路)
			{
				修改j的对应项为k;
				则从k的对应项出有可增广路,返回true;
			}
		}
	}
	则从k的对应项出没有可增广路,返回false;
}
 
void 匈牙利hungary()
{
	for i->1 to n
	{
		if (则从i的对应项出有可增广路)
			匹配数++;
	}
	输出 匹配数;
}


 

演示:

二分图匹配,匈牙利算法详解_第5张图片

二分图匹配,匈牙利算法详解_第6张图片

二分图匹配,匈牙利算法详解_第7张图片

二分图匹配,匈牙利算法详解_第8张图片

二分图匹配,匈牙利算法详解_第9张图片

二分图匹配,匈牙利算法详解_第10张图片

二分图匹配,匈牙利算法详解_第11张图片

二分图匹配,匈牙利算法详解_第12张图片

二分图匹配,匈牙利算法详解_第13张图片

二分图匹配,匈牙利算法详解_第14张图片

二分图匹配,匈牙利算法详解_第15张图片

二分图匹配,匈牙利算法详解_第16张图片

二分图匹配,匈牙利算法详解_第17张图片

二分图匹配,匈牙利算法详解_第18张图片

二分图匹配,匈牙利算法详解_第19张图片

二分图匹配,匈牙利算法详解_第20张图片

二分图匹配,匈牙利算法详解_第21张图片

二分图匹配,匈牙利算法详解_第22张图片

二分图匹配,匈牙利算法详解_第23张图片

二分图匹配,匈牙利算法详解_第24张图片

二分图匹配,匈牙利算法详解_第25张图片

二分图匹配,匈牙利算法详解_第26张图片

二分图匹配,匈牙利算法详解_第27张图片

 

c++匈牙利算法实现模板详解

/*===========================================================*\
G为图,M为图中的一个匹配,从X集合到Y集合找一个最大匹配
交互道路:对于G的一个匹配M, G中属于M与不属于M的边交替出现的道路
称为一条交互道路.
可增广道路:设P是关于匹配M的一条交互道路,如果P的两个端点是关于
M的非饱和点,那么称P是一条可增广道路。

\*===========================================================*/
int uN, vN; // uN为集合X的个数, vN为集合Y的个数,要初始化!!!
bool g[MAXN][MAXN]; // g[i][j] 表示xi与yj相连
int xM[MAXN], yM[MAXN]; // 输出量
bool chk[MAXN]; // 辅助量检查某轮y[v]是否被check
bool SearchPath(int u){
int v;
for(v = 0; v < vN; v++)
if(g[u][v] && !chk[v])//取u的临界点集合为Y,并且Y没有被访问过
{
chk[v] = true;
if(yM[v] == -1 || SearchPath(yM[v]))//若Y中有非饱和点(-1),则找到一条增广路径;
//若Y已饱和,则找到在匹配M中的边(x,y),x的集合加到X中,
//延长路径(-1->饱和Y->饱和X->(找非饱和点)),SearchPath(yM[v])找到Y中的一个非饱和点
{
yM[v] = u; xM[u] = v;//进行值更新
return true ;
}
}
return false ;
}
int MaxMatch(){
int u, ret = 0 ;
memset(xM, -1, sizeof (xM));//-1表示为非饱和点
memset(yM, -1, sizeof (yM));//-1表示为非饱和点
for(u = 0; u < uN; u++)
if(xM[u] == -1){// 在集合X中找任一非饱和点进行一次增广路径的查找
memset(chk, false, sizeof (chk));
if(SearchPath(u)) ret++;//如果找到一条增广路径,最大匹配的个数加1
}
return ret;
}

你可能感兴趣的:(模板)