二分图的最大匹配————匈牙利算法(hungary)基础详解。

二分图的定义:

简单来说,就是将图G的顶点集V划分成两部分。假设为A和B。图G的边集中的任意一条边的两个端点分别属于集合A B,这样的图就叫二分图(也叫二部图)。

匹配的定义:

给定一个二分图G,在G的一个子图M中,M的边集中的任意两条边都不依附于同一个顶点,则称M是一个匹配。

最大匹配定义:

满足上述匹配定义的M中最大(点最多,边最多)的那一个子图称为G的最大匹配。(最大匹配的结果是一个边集!可以理解成边的数目!其实是组合数)

如果一个匹配中,|V1|<=|V2|且匹配数|M|=|V1|则称此匹配为完全匹配,也称作完备匹配。特别的当|V1|=|V2|称为完美匹配


1.判断一个无向图是否为二分图

  数学的证明是十分麻烦的...然而计算机可以直接搜索...(思路参考http://blog.csdn.net/joy_go/article/details/8567069)  

 思路是这样的:

 因为G的点集分成了AB两个集合,假设A集合的点标记为黑色,B集合的点标记为白色。

 如果以一个点为顶点,所有和它有联系的边的端点中,有一个颜色和它是一样的,说明这个无向图不是二分图。

 而“如果以一个点为顶点,所有和它有联系的边的端点中”这就是一种BFS的思想,直接用BFS即可,下面给出代码片段。

bool is_BipartiteGraphy()
{
	int color[num];
	int vis[num];
	
	memset(color,0,sizeof(color));//0代表白色,B集合
	memset(vis,0,sizeof(vis));//是否访问过 
	
	color[start] = 1;//起始点标记为黑色,A集合
	vis[start] = 1;
	Q.push(start);
	while(!Q.empty())
	{
		now = Q.front();
		Q.pop();
		for(int i = 1 ; i <= num ; ++i)
		{
			if(!vis[i] && G[now][i])
			{
				if(color[i] != color[now])
				{
					color[i] = !color[now];
					vis[i] = 1;
					Q.push(i);
				}
				else
					return false;
			}
		}
	} 
	return true;
}</span>
2.求无向图的最大匹配————匈牙利算法

首先介绍几个概念:

假设M是G的一个匹配。

M——交错路

path是属于G的一条通路。path中属于M的边不属于M但属于G的边交替出现,则称path是M的一条交错路。

(也可这样描述:设path是图G的一条路,如果path的任意两条相邻的边一定是一条属于M而另一条不属于M,就称path是一条交错路。)


M——饱和点

对于点V属于G。如果V是M中的一点,那么V就是M的饱和点,否则称为非M饱和点。


M——可增广路

交错路的两个顶点都是未饱和点,这样的交错路称为可增广路。


有了以上三个概念,给出匈牙利算法的基本描述。(???原理不懂???)


摘自——https://www.byvoid.com/blog/hungary/(强烈推荐此博客!!里边有图示详解)

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的对应项出有可增广路)
            匹配数++;
    }
    输出 匹配数;
}
简单练手题目——HDU 2063

http://acm.hdu.edu.cn/showproblem.php?pid=2063




  


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值