Hopcroft-Karp 算法
Posted ayoh-loop
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hopcroft-Karp 算法相关的知识,希望对你有一定的参考价值。
1 //Hopcroft-Karp 算法 时间复杂度为O(n^(1/2)*m) 2 //该算法是对匈牙利算法的优化,利用匈牙利算法一次只能找到一条增广路径, 3 //Hopcroft-Karp就提出一次找到多条不相交的增广路径(不相交就是没有公共点和公共边的增广路径),称为增广路集 4 //然后根据这些增广路径添加多个匹配,并逐渐增加增广路径集中增广路径的长度。 5 #include <iostream> 6 #include <stdio.h> 7 #include <cstring> 8 #include <cmath> 9 #include <vector> 10 //#include <map> 11 #include <queue> 12 #include <set> 13 #define MAX 3003 14 #define INF 0x3f3f3f3f 15 16 using namespace std; 17 int nextLeft[MAX],nextRight[MAX]; //nextLeft[MAX]是左集合匹配右集合的点,同理nextRight也是 18 int dLeft[MAX],dRight[MAX]; //dLeft[MAX],dRight[MAX]是增广路径长度,或者说BFS深度 19 int dx[MAX],dy[MAX]; 20 int map[MAX][MAX]; //map[MAX][MAX]存图 21 int nx,ny; //nx,ny分别是左集合点个数,右集合点个数 22 int dis; 23 int vis[MAX]; //标记数组. 24 25 bool searchPath() //寻找增广路径集,其增广路径集中每条增广路径长度一样 26 queue<int>Q; 27 dis = INF; 28 memset(dLeft,-1,sizeof(dLeft)); 29 memset(dRight,-1,sizeof(dRight)); 30 for (int i = 1;i <= nx; i++) //在BFS中宽度搜索 31 if (-1 == nextLeft[i]) //将未遍历的节点 入队 并初始化次节点距离为0 32 Q.push(i); 33 dLeft[i] = 0; 34 35 36 while (!Q.empty()) //广度搜索增广路径 37 int u = Q.front(); 38 Q.pop(); 39 if (dLeft[u] > dis) break; 40 for (int v = 1; v <= ny; v++) //取右侧节点 41 if (map[u][v] && -1==dRight[v]) //右侧节点的增广路径的距离 42 dRight[v] = dLeft[u]+1; //v对应的距离 为u对应距离加1 43 if (-1 == nextRight[v]) dis = dRight[v]; 44 else 45 dLeft[nextRight[v]] = dRight[v]+1; 46 Q.push(nextRight[v]); 47 48 49 50 51 return dis != INF; 52 53 bool Find(int u) //Find函数,对增广路径集进行增广。 54 for (int v = 1; v <= ny; v++) 55 if (!vis[v] && map[u][v] && dRight[v] == dLeft[u]+1) 56 vis[v] = 1; 57 if (nextRight[v] != -1 && dRight[v] == dis) continue; 58 if (-1 == nextRight[v] || Find(nextRight[v])) 59 nextRight[v] = u;nextLeft[u] = v; 60 return true; 61 62 63 64 return false; 65 66 int MaxMatch() 67 int ans(0); 68 memset(nextRight,-1,sizeof(nextRight)); 69 memset(nextLeft,-1,sizeof(nextLeft)); 70 while(searchPath()) //不断进行增广路径集的操作,其增广路径也不断增长。 71 memset(vis,0,sizeof(vis)); 72 for (int i = 1; i <= nx; i++) 73 if (-1 == nextLeft[i]) 74 if (Find(i)) ans++; 75 76 77 78 return ans; 79 80 81 int main(int argc,char *argv[]) 82 // int n,m,e; 83 int e; 84 scanf("%d%d%d", &nx,&ny,&e); 85 for (int i = 1; i <= e; i++) 86 int u,v; 87 scanf("%d%d", &u,&v); 88 if (u>=1&&u<=nx&&v>=1&&v<=ny) 89 map[u][v] = 1; 90 91 92 printf("%d\n", MaxMatch()); 93 return 0; 94
以上是关于Hopcroft-Karp 算法的主要内容,如果未能解决你的问题,请参考以下文章
HDU 5727 - Necklace - [全排列+二分图匹配][Hopcroft-Karp算法模板]
Java 虚拟机原理垃圾回收算法 ( 标记-清除算法 | 复制算法 | 标记-整理算法 )