最大匹配之匈牙利算法模板。。
2011-08-11 19:01
316 查看
要学习匈牙利算法先要懂得二部图的各种概念。。下面给出由o(∩_∩)o MiYu 总结的一般性概念,这些概念很重要,一定要懂。。
二分图的基本概念: ( 意思就是所有的点分成了2个集合 x, y. 每个集合中的顶点相互间没有边 )
一个无向图 G = < V, E >, 如果存在两个集合X, Y, 使得X∪Y=V, X∩Y=Φ, 并且每一条边e={x, y}
有x∈X,y∈Y, 则称G为一个二分图(bipartite graph). 常用来表示一个二分图. 若对X中任一x及Y中任一y
恰有一边e∈E, 使e = {x, y}, 则称G为完全二分图(complete bipartite graph).
二分图的性质: ( 交错轨 和增广路的概念很重要 )
定理:无向图G为二分图的充分必要条件是,G至少有两个顶点,且其所有回路的长度均为偶数.
匹配:设G=为二分图,如果M⊆E,并且M中没有任何两边有公共端点。M=Φ时称M为空匹配.
盖点: 若M是二分图的一个匹配, 将M中的边多所关联的顶点称为盖点, 其余则为 未盖点.
交错轨: 若一条路径上属于M的边和不属于M 的边交替出现, 则称该路径为交错轨.
增广路径: 若 路径 P 是一条起始点和 终点都是未盖点的交错轨, 那么 P 称为 M 的增广路径.
最大匹配: G的所有匹配中边数最多的匹配称为最大匹配.
性质1 : 一条关于M的增广路径的长度必为奇数, 且路上的第一条边和最后一条边都不属于M.
性质2 : 对于一条关于M的增广路径 P, 将M 中属于P的边删去, 将P中不属于M 的边添加到M中,
所得到的边集合计为 M Θ P, 则 M Θ P 比 M 多一条匹配边.
性质3 : M 为 G 的一个最大匹配当且仅当不存在关于M的增广路径.
hall 定理 : 对于二分图 G = ( X, Y, E ) , 存在一个匹配M, 使得 X 的所有顶点关于M饱和
的充要条件是: 对 X 的任一子集A , 对A邻接的点集为P (A), 恒有 : | P[A] | >= | A |
其中 性质 2 和性质 3 和 hall 定理的充分性证明 就是 匈牙利算法的基础…..
二分图的 最小顶点覆盖 ==== 最大匹配
DAG图的 最小路径覆盖数 == 节点数 – 最大匹配数
二分图的 最大独立集数 = 节点数 – 最大匹配数
在二分图中求最少的点,让每条边都至少和其中的一个点关联,这就是
二分图的“最小顶点覆盖”。
最小路径覆盖 :
一个PXP的有向图中,路径覆盖就是在图中找一些路经,使之覆
盖了图中的所有顶点,且任何一个顶点有且只有一条路径与之关联;(
如果把这些路径中的每条路径从它的起始点走到它的终点,那么恰好可以
经过图中的每个顶点一次且仅一次);如果不考虑图中存在回路,那么每
每条路径就是一个弱连通子集.
由上面可以得出:
1.一个单独的顶点是一条路径;
2.如果存在一路径p1,p2,……pk,其中p1 为起点,pk为终点,那
么在覆盖图中,顶点p1,p2,……pk不再与其它的顶点之间存在有向边.
最小路径覆盖就是找出最小的路径条数,使之成为P的一个路径覆盖.
路径覆盖与二分图匹配的关系(必须是没有圈的有向图):
最小路径覆盖=|P|-最大匹配数;
其中最大匹配数的求法是把P中的每个顶点pi分成两个顶点pi’与pi”,
如果在p中存在一条pi到pj的边,那么在二分图P'中就有一条连接pi’与
pj”的无向边;这里pi’ 就是p中pi的出边,pj”就是p中pj 的一条入边;
对于公式:最小路径覆盖=|P|-最大匹配数;可以这么来理解;
如果匹配数为零,那么P中不存在有向边,于是显然有:
最小路径覆盖=|P|-最大匹配数=|P|-0=|P|;即P
的最小路径覆盖数为|P|;
P'中不在于匹配边时,路径覆盖数为|P|;
如果在P'中增加一条匹配边pi’-->pj”,那么在图P的路径覆盖
中就存在一条由pi连接pj的边,也就是说pi与pj 在一条路径上,于是路
径覆盖数就可以减少一个;
如此继续增加匹配边,每增加一条,路径覆盖数就减少一条;直到
匹配边不能继续增加时,路径覆盖数也不能再减少了,此时就有了前面
的公式;但是这里只 是说明了每条匹配边对应于路径覆盖中的一条路径
上的一条连接两个点之间的有向边;下面来说明一个路径覆盖中的每条
连接两个顶点之间的有向边对应于一条匹配 边;
与前面类似,对于路径覆盖中的每条连接两个顶点之间的每条有向
边pi—>pj,我们可以在匹配图中对应做一条连接pi’与pj”的边, 显然这
样做出来图的是一个匹配图(这一点用反证法很容易证明,如果得到的图
不是一个匹配图,那么这个图中必定存在这样两条边 pi’—pj” 及 pi’ —-pk”,
(j!=k),那么在路径覆盖图中就存在了两条边pi–>pj, pi—>pk ,那边从
pi出发的路径就不止一条了,这与路径覆盖图是矛盾的;还有另外一种情况就
是存在pi’—pj”,pk’—pj”,这种情况也类似可证);
至此,就说明了匹配边与路径覆盖图中连接两顶点之间边的一一对应关系,
那么也就说明了前面的公式成立!
匈牙利算法的原理为:从当前匹配(如果没有匹配,则初始匹配为0)出发,检查每一个未盖点,然后从它出发寻找可增广路,找到可增广路,则沿着这条可增广路进行扩充,直到不存在可增广路为止。
根据从未盖点出发寻找可增广路搜索的方法,可以分为:
1) DFS 增广
2) BFS增广
3) 多增广路(Hopcroft-Karp算法)
然后是匈牙利的模板:
结合HDU 1240 Asteroids来给出模板:
题意就是把给出点连起来,就是求最小点覆盖
#include <iostream>
#include <math.h>
using namespace std;
#define MAX 502
int map[MAX][MAX];
int n,k;
int mk[MAX];
//从X集合中的顶点u出发用深度优先的策略寻找增广路
//(这种增广路只能使当前的匹配数增加1)
int nx,ny; //X和Y集合中顶点的个数
int cx[MAX],cy[MAX];
//cx[i]表示最终求得的最大匹配中与Xi匹配的Y顶点, cy[i]同理
int path(int u)
{
for(int v=1; v<=ny; v++) //考虑所有Yi顶点v
{
if(map[u][v]&&!mk[v])
{
mk[v]=1;
//如果v没有匹配,或者如果v已经匹配了,
//但从y[v]出发可以找到一条增广路
if(cy[v]==-1|| path(cy[v]))
{
cx[u] = v; //把v匹配给u
cy[v] = u; //把u匹配给v
return 1; //找到可增广路
}
}
}
return 0 ; //如果不存在从u出发的增广路
}
int MaxMatch() //求二部图最大匹配的匈牙利算法
{
int res=0;
memset(cx,0xff,sizeof(cx)); //从0匹配开始增广
memset(cy,0xff,sizeof(cy));
for(int i=1; i<=nx; i++)
{
if(cx[i]==-1) //从每个未盖点出发进行寻找增广路
{
memset(mk,0,sizeof(mk));
res+=path(i); //每找到一条增广路,可使得匹配数加1
}
}
return res;
}
int main()
{
int i,j;
int a,b;
while(cin>>n>>k)
{
nx=n;ny=n;
memset(map,0,sizeof(map));
for(i=0;i<k;i++)
{
cin>>a>>b;
map[a]=1;
}
int max=MaxMatch();
cout<<max<<endl;
}
return 0;
}
下面把BFS的模板给出:
[b]int pred[maxn] , mk[maxn] , open[maxn] ;
int MaxMatch()
{
int i , u , v , t , d , e , cur , tail , res(0);
memset(mk , 0xff , sizeof(mk)) ;
memset(cx , 0xff , sizeof(cx)) ;
memset(cy , 0xff , sizeof(cy)) ;
for (i = 0 ; i < nx ; i++)
{
pred[i] = -1 ;
for (open[cur = tail = 0] = i ; cur <= tail && cx[i] == -1 ; cur++)
{
for (u = open[cur] , v = 0 ; v < ny && cx[i] == -1 ; v ++)
{
if (g[u][v] && mk[v] != i)
{
mk[v] = i ;
open[++tail] = cy[v] ;
if (open[tail] >= 0)
{ pred[open[tail]] = u ; continue ; }
for (d = u , e = v ; d != -1 ;
t = cx[d], cx[d] = e, cy[e] = d, e = t, d = pred[d]);
}
}
}
if (cx[i] != -1) res++ ;
}//end of for
return res ;
}
二分图的基本概念: ( 意思就是所有的点分成了2个集合 x, y. 每个集合中的顶点相互间没有边 )
一个无向图 G = < V, E >, 如果存在两个集合X, Y, 使得X∪Y=V, X∩Y=Φ, 并且每一条边e={x, y}
有x∈X,y∈Y, 则称G为一个二分图(bipartite graph). 常用来表示一个二分图. 若对X中任一x及Y中任一y
恰有一边e∈E, 使e = {x, y}, 则称G为完全二分图(complete bipartite graph).
二分图的性质: ( 交错轨 和增广路的概念很重要 )
定理:无向图G为二分图的充分必要条件是,G至少有两个顶点,且其所有回路的长度均为偶数.
匹配:设G=为二分图,如果M⊆E,并且M中没有任何两边有公共端点。M=Φ时称M为空匹配.
盖点: 若M是二分图的一个匹配, 将M中的边多所关联的顶点称为盖点, 其余则为 未盖点.
交错轨: 若一条路径上属于M的边和不属于M 的边交替出现, 则称该路径为交错轨.
增广路径: 若 路径 P 是一条起始点和 终点都是未盖点的交错轨, 那么 P 称为 M 的增广路径.
最大匹配: G的所有匹配中边数最多的匹配称为最大匹配.
性质1 : 一条关于M的增广路径的长度必为奇数, 且路上的第一条边和最后一条边都不属于M.
性质2 : 对于一条关于M的增广路径 P, 将M 中属于P的边删去, 将P中不属于M 的边添加到M中,
所得到的边集合计为 M Θ P, 则 M Θ P 比 M 多一条匹配边.
性质3 : M 为 G 的一个最大匹配当且仅当不存在关于M的增广路径.
hall 定理 : 对于二分图 G = ( X, Y, E ) , 存在一个匹配M, 使得 X 的所有顶点关于M饱和
的充要条件是: 对 X 的任一子集A , 对A邻接的点集为P (A), 恒有 : | P[A] | >= | A |
其中 性质 2 和性质 3 和 hall 定理的充分性证明 就是 匈牙利算法的基础…..
二分图的 最小顶点覆盖 ==== 最大匹配
DAG图的 最小路径覆盖数 == 节点数 – 最大匹配数
二分图的 最大独立集数 = 节点数 – 最大匹配数
在二分图中求最少的点,让每条边都至少和其中的一个点关联,这就是
二分图的“最小顶点覆盖”。
最小路径覆盖 :
一个PXP的有向图中,路径覆盖就是在图中找一些路经,使之覆
盖了图中的所有顶点,且任何一个顶点有且只有一条路径与之关联;(
如果把这些路径中的每条路径从它的起始点走到它的终点,那么恰好可以
经过图中的每个顶点一次且仅一次);如果不考虑图中存在回路,那么每
每条路径就是一个弱连通子集.
由上面可以得出:
1.一个单独的顶点是一条路径;
2.如果存在一路径p1,p2,……pk,其中p1 为起点,pk为终点,那
么在覆盖图中,顶点p1,p2,……pk不再与其它的顶点之间存在有向边.
最小路径覆盖就是找出最小的路径条数,使之成为P的一个路径覆盖.
路径覆盖与二分图匹配的关系(必须是没有圈的有向图):
最小路径覆盖=|P|-最大匹配数;
其中最大匹配数的求法是把P中的每个顶点pi分成两个顶点pi’与pi”,
如果在p中存在一条pi到pj的边,那么在二分图P'中就有一条连接pi’与
pj”的无向边;这里pi’ 就是p中pi的出边,pj”就是p中pj 的一条入边;
对于公式:最小路径覆盖=|P|-最大匹配数;可以这么来理解;
如果匹配数为零,那么P中不存在有向边,于是显然有:
最小路径覆盖=|P|-最大匹配数=|P|-0=|P|;即P
的最小路径覆盖数为|P|;
P'中不在于匹配边时,路径覆盖数为|P|;
如果在P'中增加一条匹配边pi’-->pj”,那么在图P的路径覆盖
中就存在一条由pi连接pj的边,也就是说pi与pj 在一条路径上,于是路
径覆盖数就可以减少一个;
如此继续增加匹配边,每增加一条,路径覆盖数就减少一条;直到
匹配边不能继续增加时,路径覆盖数也不能再减少了,此时就有了前面
的公式;但是这里只 是说明了每条匹配边对应于路径覆盖中的一条路径
上的一条连接两个点之间的有向边;下面来说明一个路径覆盖中的每条
连接两个顶点之间的有向边对应于一条匹配 边;
与前面类似,对于路径覆盖中的每条连接两个顶点之间的每条有向
边pi—>pj,我们可以在匹配图中对应做一条连接pi’与pj”的边, 显然这
样做出来图的是一个匹配图(这一点用反证法很容易证明,如果得到的图
不是一个匹配图,那么这个图中必定存在这样两条边 pi’—pj” 及 pi’ —-pk”,
(j!=k),那么在路径覆盖图中就存在了两条边pi–>pj, pi—>pk ,那边从
pi出发的路径就不止一条了,这与路径覆盖图是矛盾的;还有另外一种情况就
是存在pi’—pj”,pk’—pj”,这种情况也类似可证);
至此,就说明了匹配边与路径覆盖图中连接两顶点之间边的一一对应关系,
那么也就说明了前面的公式成立!
匈牙利算法的原理为:从当前匹配(如果没有匹配,则初始匹配为0)出发,检查每一个未盖点,然后从它出发寻找可增广路,找到可增广路,则沿着这条可增广路进行扩充,直到不存在可增广路为止。
根据从未盖点出发寻找可增广路搜索的方法,可以分为:
1) DFS 增广
2) BFS增广
3) 多增广路(Hopcroft-Karp算法)
然后是匈牙利的模板:
结合HDU 1240 Asteroids来给出模板:
题意就是把给出点连起来,就是求最小点覆盖
#include <iostream>
#include <math.h>
using namespace std;
#define MAX 502
int map[MAX][MAX];
int n,k;
int mk[MAX];
//从X集合中的顶点u出发用深度优先的策略寻找增广路
//(这种增广路只能使当前的匹配数增加1)
int nx,ny; //X和Y集合中顶点的个数
int cx[MAX],cy[MAX];
//cx[i]表示最终求得的最大匹配中与Xi匹配的Y顶点, cy[i]同理
int path(int u)
{
for(int v=1; v<=ny; v++) //考虑所有Yi顶点v
{
if(map[u][v]&&!mk[v])
{
mk[v]=1;
//如果v没有匹配,或者如果v已经匹配了,
//但从y[v]出发可以找到一条增广路
if(cy[v]==-1|| path(cy[v]))
{
cx[u] = v; //把v匹配给u
cy[v] = u; //把u匹配给v
return 1; //找到可增广路
}
}
}
return 0 ; //如果不存在从u出发的增广路
}
int MaxMatch() //求二部图最大匹配的匈牙利算法
{
int res=0;
memset(cx,0xff,sizeof(cx)); //从0匹配开始增广
memset(cy,0xff,sizeof(cy));
for(int i=1; i<=nx; i++)
{
if(cx[i]==-1) //从每个未盖点出发进行寻找增广路
{
memset(mk,0,sizeof(mk));
res+=path(i); //每找到一条增广路,可使得匹配数加1
}
}
return res;
}
int main()
{
int i,j;
int a,b;
while(cin>>n>>k)
{
nx=n;ny=n;
memset(map,0,sizeof(map));
for(i=0;i<k;i++)
{
cin>>a>>b;
map[a]=1;
}
int max=MaxMatch();
cout<<max<<endl;
}
return 0;
}
下面把BFS的模板给出:
[b]int pred[maxn] , mk[maxn] , open[maxn] ;
int MaxMatch()
{
int i , u , v , t , d , e , cur , tail , res(0);
memset(mk , 0xff , sizeof(mk)) ;
memset(cx , 0xff , sizeof(cx)) ;
memset(cy , 0xff , sizeof(cy)) ;
for (i = 0 ; i < nx ; i++)
{
pred[i] = -1 ;
for (open[cur = tail = 0] = i ; cur <= tail && cx[i] == -1 ; cur++)
{
for (u = open[cur] , v = 0 ; v < ny && cx[i] == -1 ; v ++)
{
if (g[u][v] && mk[v] != i)
{
mk[v] = i ;
open[++tail] = cy[v] ;
if (open[tail] >= 0)
{ pred[open[tail]] = u ; continue ; }
for (d = u , e = v ; d != -1 ;
t = cx[d], cx[d] = e, cy[e] = d, e = t, d = pred[d]);
}
}
}
if (cx[i] != -1) res++ ;
}//end of for
return res ;
}
相关文章推荐
- 51Nod 飞行员配对(二分图最大匹配)(匈牙利算法模板题)
- 最大匹配之匈牙利算法模板。。 (转)
- 【模板】匈牙利算法——二分图最大匹配
- 最大二分匹配 匈牙利算法模板&&POJ 1469 COURSES
- 最大匹配之匈牙利算法模板。。
- (模板题)poj 3041 Asteroids(二分图的最大匹配匈牙利算法)
- 【HDUOJ2063】 过山车(最大匹配数,匈牙利算法,模板题)
- 二分图最大匹配匈牙利算法(poj)3041(模板)
- 匈牙利算法,二分图最大匹配、多重匹配模板
- 二分图最大匹配(匈牙利算法Dfs模板)
- 【二分匹配】【匈牙利算法即由增广路求最大匹配模板】
- 求二分图最大匹配——匈牙利算法模板。
- 二分图最大匹配算法-匈牙利算法(Hungary)模板
- 二分图最大匹配之匈牙利算法模板
- 透彻解析二分图最大匹配匈牙利算法模板
- 【模板】二分图最大匹配(匈牙利算法)
- poj3041 最小点覆盖即最大匹配(匈牙利算法)(模板)
- hdu 1054 Strategic Game(模板) 最大二分匹配,最小点覆盖 匈牙利算法
- 模板_matlab 匈牙利算法(最大匹配数/最小覆盖点)
- 【模板】匈牙利算法 二分图最大匹配题模板