TheAlgorithms/C++
1.0.0
All the algorithms implemented in C++
Toggle main menu visibility
Loading...
Searching...
No Matches
hopcroft_karp.cpp
Go to the documentation of this file.
1
46
47
48
#include <iostream>
49
#include <cstdlib>
50
#include <queue>
51
#include <list>
52
#include <climits>
53
#include <memory>
54
#include <cassert>
55
60
namespace
graph
{
61
66
class
HKGraph
67
{
68
int
m
{};
69
int
n
{};
70
const
int
NIL{0};
71
const
int
INF
{INT_MAX};
72
73
std::vector<std::list<int> >
adj
;
74
75
std::vector<int>
pair_u
;
76
std::vector<int>
pair_v
;
77
std::vector<int>
dist
;
78
79
public
:
80
HKGraph
();
// Default Constructor
81
HKGraph
(
int
m
,
int
n
);
// Constructor
82
void
addEdge
(
int
u,
int
v);
// To add edge
83
84
bool
bfs
();
// Returns true if there is an augmenting path
85
bool
dfs
(
int
u);
// Adds augmenting path if there is one beginning with u
86
87
int
hopcroftKarpAlgorithm
();
// Returns size of maximum matching
88
};
89
90
95
int
HKGraph::hopcroftKarpAlgorithm
()
96
{
97
98
// pair_u[u] stores pair of u in matching on left side of Bipartite Graph.
99
// If u doesn't have any pair, then pair_u[u] is NIL
100
pair_u
= std::vector<int>(
m
+ 1,NIL);
101
102
// pair_v[v] stores pair of v in matching on right side of Biparite Graph.
103
// If v doesn't have any pair, then pair_u[v] is NIL
104
pair_v
= std::vector<int>(
n
+ 1,NIL);
105
106
dist
= std::vector<int>(
m
+ 1);
// dist[u] stores distance of left side vertices
107
108
int
result = 0;
// Initialize result
109
110
// Keep updating the result while there is an augmenting path possible.
111
while
(
bfs
())
112
{
113
// Find a free vertex to check for a matching
114
for
(
int
u = 1; u <=
m
; u++){
115
116
// If current vertex is free and there is
117
// an augmenting path from current vertex
118
// then increment the result
119
if
(
pair_u
[u] == NIL &&
dfs
(u)){
120
result++;
121
}
122
}
123
}
124
return
result;
125
}
126
127
133
bool
HKGraph::bfs
()
134
{
135
std::queue<int> q;
// an integer queue for bfs
136
137
// First layer of vertices (set distance as 0)
138
for
(
int
u = 1; u <=
m
; u++)
139
{
140
// If this is a free vertex, add it to queue
141
if
(
pair_u
[u] == NIL){
142
143
dist
[u] = 0;
// u is not matched so distance is 0
144
q.push(u);
145
}
146
147
else
{
148
dist
[u] = INF;
// set distance as infinite so that this vertex is considered next time for availibility
149
}
150
}
151
152
153
dist
[NIL] = INF;
// Initialize distance to NIL as infinite
154
155
// q is going to contain vertices of left side only.
156
while
(!q.empty())
157
{
158
int
u = q.front();
// dequeue a vertex
159
q.pop();
160
161
// If this node is not NIL and can provide a shorter path to NIL then
162
if
(
dist
[u] <
dist
[NIL])
163
{
164
// Get all the adjacent vertices of the dequeued vertex u
165
std::list<int>::iterator it;
166
for
(it =
adj
[u].begin(); it !=
adj
[u].end(); ++it)
167
{
168
int
v = *it;
169
170
// If pair of v is not considered so far i.e. (v, pair_v[v]) is not yet explored edge.
171
if
(
dist
[
pair_v
[v]] == INF)
172
{
173
dist
[
pair_v
[v]] =
dist
[u] + 1;
174
q.push(
pair_v
[v]);
// Consider the pair and push it to queue
175
}
176
}
177
}
178
}
179
180
181
182
return
(
dist
[NIL] != INF);
// If we could come back to NIL using alternating path of distinct vertices then there is an augmenting path available
183
}
184
191
bool
HKGraph::dfs
(
int
u)
192
{
193
if
(u != NIL)
194
{
195
std::list<int>::iterator it;
196
for
(it =
adj
[u].begin(); it !=
adj
[u].end(); ++it)
197
{
198
199
int
v = *it;
// Adjacent vertex of u
200
201
// Follow the distances set by BFS search
202
if
(
dist
[
pair_v
[v]] ==
dist
[u] + 1)
203
{
204
// If dfs for pair of v also return true then new matching possible, store the matching
205
if
(
dfs
(
pair_v
[v]) ==
true
)
206
{
207
pair_v
[v] = u;
208
pair_u
[u] = v;
209
return
true
;
210
}
211
}
212
}
213
214
215
dist
[u] = INF;
// If there is no augmenting path beginning with u then set distance to infinite.
216
return
false
;
217
}
218
return
true
;
219
}
220
224
HKGraph::HKGraph
() =
default
;
225
231
HKGraph::HKGraph
(
int
m
,
int
n
) {
232
this->m =
m
;
233
this->n =
n
;
234
adj
= std::vector<std::list<int> >(
m
+ 1);
235
}
236
242
void
HKGraph::addEdge
(
int
u,
int
v)
243
{
244
adj
[u].push_back(v);
// Add v to u’s list.
245
}
246
247
}
// namespace graph
248
249
using
graph::HKGraph
;
250
255
void
tests
(){
256
// Sample test case 1
257
int
v1a = 3, v1b = 5;
// vertices of left side, right side and edges
258
HKGraph
g1(v1a, v1b);
// execute the algorithm
259
260
g1.
addEdge
(0,1);
261
g1.
addEdge
(1,4);
262
263
int
expected_res1 = 0;
// for the above sample data, this is the expected output
264
int
res1 = g1.
hopcroftKarpAlgorithm
();
265
266
assert(res1 == expected_res1);
// assert check to ensure that the algorithm executed correctly for test 1
267
268
// Sample test case 2
269
int
v2a = 4, v2b = 4;
// vertices of left side, right side and edges
270
HKGraph
g2(v2a, v2b);
// execute the algorithm
271
272
g2.
addEdge
(1,1);
273
g2.
addEdge
(1,3);
274
g2.
addEdge
(2,3);
275
g2.
addEdge
(3,4);
276
g2.
addEdge
(4,3);
277
g2.
addEdge
(4,2);
278
279
int
expected_res2 = 0;
// for the above sample data, this is the expected output
280
int
res2 = g2.
hopcroftKarpAlgorithm
();
281
282
assert(res2 == expected_res2);
// assert check to ensure that the algorithm executed correctly for test 2
283
284
// Sample test case 3
285
int
v3a = 6, v3b = 6;
// vertices of left side, right side and edges
286
HKGraph
g3(v3a, v3b);
// execute the algorithm
287
288
g3.
addEdge
(0,1);
289
g3.
addEdge
(1,4);
290
g3.
addEdge
(1,5);
291
g3.
addEdge
(5,0);
292
293
int
expected_res3 = 0;
// for the above sample data, this is the expected output
294
int
res3 = g3.
hopcroftKarpAlgorithm
();
295
296
assert(res3 == expected_res3);
// assert check to ensure that the algorithm executed correctly for test 3
297
298
299
300
}
301
306
int
main
()
307
{
308
tests
();
// perform self-tests
309
310
int
v1 = 0, v2 = 0, e = 0;
311
std::cin >> v1 >> v2 >> e;
// vertices of left side, right side and edges
312
HKGraph
g(v1, v2);
313
int
u = 0, v = 0;
314
for
(
int
i = 0; i < e; ++i)
315
{
316
std::cin >> u >> v;
317
g.addEdge(u, v);
318
}
319
320
int
res = g.hopcroftKarpAlgorithm();
321
std::cout <<
"Maximum matching is "
<< res <<
"\n"
;
322
323
return
0;
324
325
}
INF
constexpr int64_t INF
for assert
Definition
bidirectional_dijkstra.cpp:24
graph::HKGraph
Represents Bipartite graph for Hopcroft Karp implementation.
Definition
hopcroft_karp.cpp:67
graph::HKGraph::adj
std::vector< std::list< int > > adj
adj[u] stores adjacents of left side and 0 is used for dummy vertex
Definition
hopcroft_karp.cpp:73
graph::HKGraph::addEdge
void addEdge(int u, int v)
function to add edge from u to v
Definition
hopcroft_karp.cpp:242
graph::HKGraph::m
int m
m is the number of vertices on left side of Bipartite Graph
Definition
hopcroft_karp.cpp:68
graph::HKGraph::dist
std::vector< int > dist
dist represents the distance between vertex 'u' and vertex 'v'
Definition
hopcroft_karp.cpp:77
graph::HKGraph::n
int n
n is the number of vertices on right side of Bipartite Graph
Definition
hopcroft_karp.cpp:69
graph::HKGraph::bfs
bool bfs()
This function checks for the possibility of augmented path availability.
Definition
hopcroft_karp.cpp:133
graph::HKGraph::pair_u
std::vector< int > pair_u
value of vertex 'u' ranges from 1 to m
Definition
hopcroft_karp.cpp:75
graph::HKGraph::pair_v
std::vector< int > pair_v
value of vertex 'v' ranges from 1 to n
Definition
hopcroft_karp.cpp:76
graph::HKGraph::hopcroftKarpAlgorithm
int hopcroftKarpAlgorithm()
This function counts the number of augmenting paths between left and right sides of the Bipartite gra...
Definition
hopcroft_karp.cpp:95
graph::HKGraph::dfs
bool dfs(int u)
This functions checks whether an augmenting path is available exists beginning with free vertex u.
Definition
hopcroft_karp.cpp:191
graph::HKGraph::HKGraph
HKGraph()
Default Constructor for initialization.
main
int main()
Main function.
Definition
generate_parentheses.cpp:110
graph
Graph Algorithms.
tests
Testcases to check Union of Two Arrays.
graph
hopcroft_karp.cpp
Generated by
1.18.0