您的位置:首页 > 运维架构

二分匹配Hopcroft-Karp算法

2015-07-25 11:08 447 查看
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N = 110;
const int INF=0x7fffffff;
int bmap

;//每次记得清空
//对于两边各50000个点,200000条边的二分图最大匹配可以在1s内出解,效果很好:)
struct HK{//用HK算法求解二分最大匹配问题(时间复杂度为sqrt(v)*e)
int nx,ny,dis;
int cx
;//cx[i]表示左集合i顶点所匹配的右集合的顶点序号
int cy
; //cy[i]表示右集合i顶点所匹配的左集合的顶点序号
int dx
;
int dy
;
int Q
;
bool bmask
;
bool searchpath(){//极大最短增广路集
int front,rear;
front=rear=0;//初始化队列
dis=INF;
memset(dx, -1, sizeof(dx));
memset(dy, -1, sizeof(dy));
for(int i=1;i<=nx;i++){
if(cx[i]==-1)//左边未匹配
{
Q[rear++]=i;//将左边节点放入队列
dx[i]=0;//分层 所有潜在起点构成0层
}
}

while(front<rear){
int u=Q[front++];//u都是未匹配的
if(dx[u]>dis)break;
for(int v=1;v<=ny;v++){
if(bmap[u][v]&&dy[v]==-1){//相邻未分层构成i+1层。
dy[v]=dx[u]+1;//v对应的距离 为u对应距离加1
if(cy[v]==-1)dis=dy[v];//右侧未匹配,更新最短距离
else{
dx[cy[v]]=dy[v]+1;//右侧已经匹配,根据已匹配边回溯。分层
Q[rear++]=cy[v];//左侧已匹配点入队。
}
}
}
}
return dis!=INF;
}
int findpath(int u){//只搜索极大最短增广路集中的边
for(int v=1;v<=ny;v++){
if(!bmask[v]&&bmap[u][v]&&dy[v]==dx[u]+1){//反向搜索的过程
bmask[v]=1;
if(cy[v]!=-1&&dy[v]==dis)continue;
if(cy[v]==-1||findpath(cy[v])){
cy[v]=u;
cx[u]=v;
return 1;
}
}
}
return 0;
}
int Max_match(){
int res=0;
memset(cx,-1,sizeof(cx));
memset(cy,-1,sizeof(cy));
while(searchpath()){
memset(bmask, 0, sizeof(bmask));
for(int i=1;i<=nx;i++){
if(cx[i]==-1){
res+=findpath(i);
}
}
}
return res;
}
};
HK hk;
//调用的时候确定hk.nx,hk.ny,然后直接调用Max_match()就行
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: