您的位置:首页 > 其它

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

2014-08-22 09:33 295 查看
二分图的定义:

简单来说,就是将图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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: