码迷,mamicode.com
首页 > 编程语言 > 详细

Hopcroft-Karp 算法

时间:2019-09-03 09:15:17      阅读:69      评论:0      收藏:0      [点我收藏+]

标签:map   vector   相交   tor   匹配   tle   pop   入队   printf   

 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 算法

标签:map   vector   相交   tor   匹配   tle   pop   入队   printf   

原文地址:https://www.cnblogs.com/AyOh-loop/p/11450957.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!