From dcc79d0dae00bd3d4f8ce3850955a471cd504659 Mon Sep 17 00:00:00 2001
From: Bruno Freitas Tissei <bft15@inf.ufpr.br>
Date: Sun, 3 Mar 2019 22:57:11 -0300
Subject: [PATCH] Add hopcroft karp algorithm

Signed-off-by: Bruno Freitas Tissei <bft15@inf.ufpr.br>
---
 algorithms/graph/hopcroft_karp.cpp | 83 ++++++++++++++++++++++++++++++
 1 file changed, 83 insertions(+)
 create mode 100644 algorithms/graph/hopcroft_karp.cpp

diff --git a/algorithms/graph/hopcroft_karp.cpp b/algorithms/graph/hopcroft_karp.cpp
new file mode 100644
index 0000000..0969bde
--- /dev/null
+++ b/algorithms/graph/hopcroft_karp.cpp
@@ -0,0 +1,83 @@
+/**
+ * Hopcroft-Karp
+ *
+ * Complexity (Time): O(E * sqrt(V))
+ * Complexity (Space): O(V + E)
+ */
+
+int dist[MAX];
+int matchL[MAX], matchR[MAX];
+
+vector<int> graph[MAX];
+
+// Builds an alternating level graph rooted at unmatched vertices in L
+// using BFS, and returns whether there is an augmenting path in the graph
+// or not
+bool bfs(int n) {
+  queue<int> Q;
+
+  // Add unmatched vertices in L to the queue
+  for (int l = 1; l <= n; ++l)
+    if (matchL[l] == 0) {
+      dist[l] = 0;
+      Q.push(l);
+    } else
+      dist[l] = inf;
+
+  dist[0] = inf;
+  while (!Q.empty()) {
+    int l = Q.front(); Q.pop();
+
+    if (dist[l] < dist[0]) {
+      for (auto r : graph[l])
+        if (dist[matchR[r]] == inf) {
+          dist[matchR[r]] = dist[l] + 1;
+          Q.push(matchR[r]);
+        }
+    }
+  }
+
+  return (dist[0] != inf);
+}
+
+
+// Augments path starting in l if there is one, returns
+// whether a path was augmented or not 
+bool dfs(int l) {
+  if (l == 0)
+    return true;
+  
+  for (auto r : graph[l]) {
+
+    // The augmenting path has increasing dist, set by the BFS
+    if (dist[matchR[r]] == dist[l] + 1)
+      if (dfs(matchR[r])) {
+        matchR[r] = l;
+        matchL[l] = r;
+        return true;
+      }
+  }
+
+  dist[l] = inf;
+  return false;
+}
+
+
+// Returns number of matched vertices on the left (matched edges)
+int hopcroft_karp(int n) {
+  mset(matchL, 0);  
+  mset(matchR, 0);  
+
+  int ans = 0;
+
+  // While there is an augmenting path
+  while (bfs(n)) {
+
+    // Augment the path when is possible
+    for (int l = 1; l <= n; ++l)
+      if (matchL[l] == 0 && dfs(l))
+        ans++;
+  }
+
+  return ans;
+}
-- 
GitLab