TheAlgorithms/C++ 1.0.0
All the algorithms implemented in C++
Loading...
Searching...
No Matches
hopcroft_karp.cpp
Go to the documentation of this file.
1
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
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
79public:
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
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
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
191bool 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
224HKGraph::HKGraph() = default;
225
231HKGraph::HKGraph(int m, int n) {
232 this->m = m;
233 this->n = n;
234 adj = std::vector<std::list<int> >(m + 1);
235}
236
242void 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
249using graph::HKGraph;
250
255void tests(){
256 // Sample test case 1
257 int v1a = 3, v1b = 5, e1 = 2; // 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, e2 = 6; // 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, e3 = 4; // 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
306int 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}
Represents Bipartite graph for Hopcroft Karp implementation.
std::vector< std::list< int > > adj
adj[u] stores adjacents of left side and 0 is used for dummy vertex
void addEdge(int u, int v)
function to add edge from u to v
int m
m is the number of vertices on left side of Bipartite Graph
std::vector< int > dist
dist represents the distance between vertex 'u' and vertex 'v'
int n
n is the number of vertices on right side of Bipartite Graph
bool bfs()
This function checks for the possibility of augmented path availability.
std::vector< int > pair_u
value of vertex 'u' ranges from 1 to m
std::vector< int > pair_v
value of vertex 'v' ranges from 1 to n
int hopcroftKarpAlgorithm()
This function counts the number of augmenting paths between left and right sides of the Bipartite gra...
bool dfs(int u)
This functions checks whether an augmenting path is available exists beginning with free vertex u.
HKGraph()
Default Constructor for initialization.
void tests()
int main()
Main function.
Graph Algorithms.