您的位置:首页 > 其它

二分图最大匹配(匈牙利算法)

2013-02-14 14:38 190 查看


二分图最大匹配(匈牙利算法)


这两天自学了一下二分图的最大匹配(匈牙利算法)的算法,现在稍微总结一下。

(1)前提说明:(用到的定义说明)

1。二部图:

如果图G=(V,E)的顶点集何V可分为两个集合X,Y,且满足 X∪Y = V, X∩Y=Φ,则G称为二部图;图G的边集用E(G)表示,点集用V(G)表示。

2。匹配:

设M是E(G)的一个子集,如果M中任意两条边在G中均不邻接,则称M是G的一个匹配。M中的—条边的两个端点叫做在M是配对的。

3。饱和与非饱和:

若匹配M的某条边与顶点v关联,则称M饱和顶点v,并且称v是M-饱和的,否则称v是M-不饱和的。

4。交互道:

若M是二分图G=(V,E)的一个匹配。设从图G中的一个顶点到另一个顶点存在一条道路,这条道路是由属于M的边和不属于M的边交替出现组成的,则称这条道路为交互道。

5。可增广道路:

若一交互道的两端点为关于M非饱和顶点时,则称这条交互道是可增广道路。显然,一条边的两端点非饱和,则这条边也是可增广道路。

6。最大匹配:

如果M是一匹配,而不存在其它匹配M',使得|M'|>|M|,则称M是最大匹配。其中|M|表示匹配M的边数。

7。对称差:

A,B是两个集合,定义 A?B = (A∪B)\(A∩B)

则A?B称为A和B的对称差。

定理:M为G的最大匹配的充要条件是G中不存在可增广道路。

Hall定理:对于二部图G,存在一个匹配M,使得X的所有顶点关于M饱和的充要条件是:对于

X的任意一个子集A,和A邻接的点集为T(A),恒有: |T(A)| >= |A|

其中A\B表示集合A和集合B的商集,即属于A且不属于集合B的集合。

(2)定理(依据):

定理:M为G的最大匹配的充要条件是G中不存在可增广道路。

Hall定理:对于二部图G,存在一个匹配M,使得X的所有顶点关于M饱和的充要条件是:对于

X的任意一个子集A,和A邻接的点集为T(A),恒有: |T(A)| >= |A|

(3)匈牙利算法是基于Hall定理中充分性证明的思想,其——基本步骤:

1.任给初始匹配M;

2.若X已饱和则结束,否则进行第3步;

3.在X中找到一个非饱和顶点x0, 作V1 ← {x0}, V2 ← Φ;

4.若T(V1) = V2则因为无法匹配而停止,否则任选一点y ∈T(V1)\V2;

5.若y已饱和则转6,否则做一条从x0 →y的可增广道路P,M←M?E(P),转2;

6.由于y已饱和,所以M中有一条边(y,z),作 V1 ← V1 ∪{z}, V2 ← V2 ∪ {y}, 转4;

(4)基于最大匹配的其他问题求解:

1. 二分图的最小顶点覆盖(例hdu1150,poj3041)

在二分图中求最少的点,让每条边都至少和其中的一个点关联,这就是

二分图的“最小顶点覆盖”。

结论: 二分图的最小顶点覆盖数 = 二分图的最大匹配数

2. DAG图的最小路径覆盖 (例hdu1151)

用尽量少的不相交简单路径覆盖有向无环图(DAG)G的所有顶点,这就是DAG图的最小路径覆盖问题。

结论:DAG图的最小路径覆盖数= 节点数(n)- 最大匹配数(m)

3. 二分图的最大独立集(例hdu1068)

最大独立集是指求一个二分图中最大的一个点集,该点集内的点互不相连。

结论:二分图的最大独立集数= 节点数(n)- 最大匹配数(m)/2

(5)代码模板(以hdu2063为例)

#include<stdio.h>

#include<string.h>

int map[505][505];

int
dis[505],m,n,inq[505];

int
find(int t){

int
i;

for(
i=1;i<=m;i++){

if(
inq[i]==0&&map[t][i]){

inq[i]=1;

if(
dis[i]==-1||find(dis[i])){

dis[i]=t;

return
1;

}

}

}

return
0;

}

int
max(){

int
i,num;

num=0;

memset(dis,-1,sizeof(dis));

for(
i=1;i<=n;i++){

memset(inq,0,sizeof(inq));

if(
find(i))

num++;

}

return
num;

}

int main()

{

int
k,a,b;

while(
scanf("%d",&k),k!=0){

memset(map,0,sizeof(map));

scanf("%d%d",&n,&m);

while(
k--){

scanf("%d%d",&a,&b);

map[a][b]=1;

}


printf("%d\n",max());

}

return
0;

}


//inq[]相当于V2;dis[]相当于M;map[][]为记录输入的二分图;

相关练习:

HDOJ_1068 (二分图最大独立集=n-m/2)

HDOJ_1150 (二分图最小顶点覆盖=m)

HDOJ_1151 (二分图最小路径覆盖=n-m)

HDOJ_1281(求完美匹配 的个数)

HDOJ_1498(最大匹配n=遍历每个点需要的次数m)

HDOJ_1528

HDOJ_1507

POJ_2724

POJ_3216
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: