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算法模板]

求二分图最大匹配——Hopcroft-Krap算法

算法都有哪些分类

Java 虚拟机原理垃圾回收算法 ( 标记-清除算法 | 复制算法 | 标记-整理算法 )

Java 虚拟机原理垃圾回收算法 ( 标记-清除算法 | 复制算法 | 标记-整理算法 )

页面置换算法(最佳置换算法FIFO置换算法LRU置换算法LFU置换算法)