转:二分图最大匹配Hopcroft_Karp算法

 

二分图最大匹配除了匈牙利算法还有一个Hopcroft-Karp算法,匈牙利算法的复杂的为O(ne),而Hopcroft-Karp算法的

复杂度为O(en^0.5)。

     该算法的精髓在于同时找多条增广路进行反转。我们先用BFS找出可能的增广路,这里用到BFS层次搜索的概念,

记录当前结点在第几层,用于后面DFS沿增广路反转时用,然后再用DFS沿每条增广路反转。这样不停地找,直至无法找

到增广路为止。

     wiki上的说明: http://en.wikipedia.org/wiki/Hopcroft–Karp_algorithm

     推荐两道题测试该算法:

     hdu 2389

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

     这道题空间,时间都卡的比较紧,用前向星的存储方法不停TLE,最后用

vector存邻接表才过的...时间为: 343MS,还算满意~~

      SPOJ 4206

      https://www.spoj.pl/problems/MATCHING/

      裸的二分图匹配,就是用来测时间的,跑了1.43s,也还行~~

附Hopcroft-Karp算法模板:

二分图最大匹配: Hopcroft_Karp算法,复杂度: O(n^2.5).

用BFS找多条增广路,用distx, disty来记录下一个点,用DFS来遍历这些增广路.

#include using namespace std; const int maxn=201; const int maxm=40005; const int INF=INT_MAX/2; struct EDGE { int b; int next; }; int nx, ny, m; EDGE edge[maxm]; int edge_num; int first[maxn]; int cx[maxn],cy[maxn];// cx[i]表示xi对应的匹配,cy[i]表示yi对应的匹配. int distx[maxn],disty[maxn]; // 层的概念,即在BFS中的第几层. int que[maxn]; int ans; inline void Init() { fill(cx,cx+maxn,-1); fill(cy,cy+maxn,-1); fill(first,first+maxn,-1); edge_num=0; ans=0; } inline void AddEdge(int a, int b) { edge[edge_num].b=b; edge[edge_num].next=first[a],first[a]=edge_num++; } inline bool BFS() { int i,j,k; bool flag(0); int h,t; memset(distx,0,sizeof(distx)); memset(disty,0,sizeof(disty)); h=t=0; for(i=1;i<=nx;++i) if(cx[i]==-1)que[t++]=i; for(;h!=t;++h) { i=que[h]; for(k=first[i];k!=-1;k=edge[k].next) { j=edge[k].b; if(!disty[j]) { disty[j]=distx[i]+1; if(cy[j]==-1)flag=1; else distx[cy[j]]=disty[j]+1,que[t++]=cy[j]; } } } return flag; } bool DFS(int i) { int j,k; for (k=first[i];k!=-1;k=edge[k].next) { j=edge[k].b; if(disty[j]==distx[i]+1) { // 说明j是i的后继结点. disty[j]=0; // j被用过了,不能再作为其他点的后继结点了. if(cy[j]==-1||DFS(cy[j])) { cx[i]=j,cy[j]=i; return 1; } } } return 0; } inline void Hopcroft_Karp() { int i,j; while(BFS()) for(i=1;i<=nx;++i) if(cx[i]==-1 && DFS(i))++ans; } int main(void) { // freopen("Input.txt", "r", stdin); int i, j; int a, b; while (scanf("%d%d",&nx,&ny)!=EOF) { Init(); for(i=1;i<=nx;++i) { scanf("%d",&a); for(b=0;b

 

由于本人比较菜,网上找来的代码n种都看得不大明白,修改后都不能正常运行,囧。。。。就上面这个可以

以下为各种版本。。。。

BFS 版:

#include #include const int maxn=201; struct edge{int j,next;}es[maxn*maxn]; int link[maxn],dist[maxn],mk[maxn],pre[maxn],src[maxn],queue[maxn],first[maxn],n,m; void Hopcroft_KarpBFS() { int i,u,t,d,e,eofv,top,size,res=0,p,flag; memset((void*)mk,0xff,sizeof(mk)); memset((void*)link,0xff,sizeof(link)); for(p=1,flag=1;flag;++p) {//if flag=0; for(top=size=0,i=1;i<=n;++i) { if(first[i]==-1)break; if(link[i]==-1)queue[++size]=i,pre[i]=-1,src[i]=i; } for(;top<=size;++top) {//poo-up for queue u=queue[top]; if(link[src[u]]!=-1)continue;//if src[u] have already has the following child for(eofv=first[u];eofv!=-1;eofv=es[eofv].next) { if(mk[es[eofv].j]!=p) {//not the current branches, yeah mk[es[eofv].j]=p, queue[++size]=link[es[eofv].j]; if(link[es[eofv].j]!=-1) { pre[link[es[eofv].j]]=u, src[queue[size]]=src[u] ; continue ; } for(size--,flag=1,d=u,e=es[eofv].j;d!=-1;t=link[d],link[d]=e,link[e]=d,e=t,d=pre[d]); } } } } for(i=1;i<=n;++i) { if(first[i]==-1)break; ++res; } printf("%d/n",res); } int main(int argc, char* argv[]) { //freopen("car.in","r",stdin); //freopen("car.out","w",stdout); int i,j,w,tot=-1; while(scanf("%d%d",&n,&m)!=EOF) { for(i=1;i<=n;++i) { first[i]=-1; scanf("%d",&w); for(j=0;j

DFS版:

#include #include const int maxn=201; struct edge{int j,next;}es[maxn*maxn]; int link[maxn],dist[maxn],mk[maxn],pre[maxn],src[maxn],queue[maxn],first[maxn],n,m; bool HK_bfs() { bool found=0; int top=0,size=0,x; for(int i=1;i<=n;dist[i]=0,++i) if(link[i]==-1)queue[size++]=i; for(;x=queue[top],top

pascal版(这个还没测,跟第一个貌似一样):

program Project1; const maxn=1000; var dx,dy,mx,my,q:array[1..maxn]of longint; adj:array[1..maxn,0..maxn]of longint; n,m,e,i,j,ans,ff,rr:longint; function bfs:boolean; var i,u,j:longint; begin bfs:=false; fillchar(q,sizeof(q),0); rr:=1; ff:=1; for i:=1 to n do if mx[i]=-1 then begin q[ff]:=i; inc(ff); end; for i:=1 to max(m,n)do begin dx[i]:=0; dy[i]:=0; end; while rr

 

 

你可能感兴趣的:(算法,算法,struct,pascal,function,algorithm,vector)