From 22edf84110d24bdb6478305a0c5906e1c7c8dec8 Mon Sep 17 00:00:00 2001
From: Bruno Freitas Tissei <bft15@inf.ufpr.br>
Date: Fri, 22 Feb 2019 20:32:41 -0300
Subject: [PATCH] Add ford-fulkerson

Signed-off-by: Bruno Freitas Tissei <bft15@inf.ufpr.br>
---
 algorithms/graph/articulations_bridges.cpp |  4 +-
 algorithms/graph/bfs.cpp                   |  4 +-
 algorithms/graph/bipartite_match.cpp       |  6 +--
 algorithms/graph/dfs.cpp                   |  4 +-
 algorithms/graph/dijkstra.cpp              |  4 +-
 algorithms/graph/floyd_warshall.cpp        |  4 +-
 algorithms/graph/ford_fulkerson.cpp        | 59 ++++++++++++++++++++++
 algorithms/graph/kosaraju.cpp              |  4 +-
 algorithms/graph/kruskal.cpp               |  4 +-
 algorithms/graph/lca.cpp                   |  6 +--
 algorithms/graph/prim.cpp                  |  4 +-
 algorithms/graph/tarjan.cpp                |  4 +-
 algorithms/graph/topological_sort.cpp      |  4 +-
 algorithms/structure/lazy_segment_tree.cpp |  2 +-
 algorithms/structure/segment_tree.cpp      | 38 +++++++++-----
 notebook/gen_latex.py                      | 19 ++++---
 testing.py                                 | 53 +++++++++++++++++++
 17 files changed, 172 insertions(+), 51 deletions(-)
 create mode 100644 algorithms/graph/ford_fulkerson.cpp
 create mode 100644 testing.py

diff --git a/algorithms/graph/articulations_bridges.cpp b/algorithms/graph/articulations_bridges.cpp
index 7ddb90e..73c9b6e 100644
--- a/algorithms/graph/articulations_bridges.cpp
+++ b/algorithms/graph/articulations_bridges.cpp
@@ -1,8 +1,8 @@
 /**
  * Tarjan - Articulations and Bridges
  *
- * Complexity (Time): O(n + m)
- * Complexity (Space): O(n + m)
+ * Complexity (Time): O(V + E)
+ * Complexity (Space): O(V + E)
  */
 
 vector<int> graph[MAX];
diff --git a/algorithms/graph/bfs.cpp b/algorithms/graph/bfs.cpp
index 6431f2b..2317e9a 100644
--- a/algorithms/graph/bfs.cpp
+++ b/algorithms/graph/bfs.cpp
@@ -1,8 +1,8 @@
 /**
  * Breadth First Search (BFS)
  *
- * Complexity (Time): O(n + m)
- * Complexity (Space): O(n + m)
+ * Complexity (Time): O(V + E)
+ * Complexity (Space): O(V + E)
  */
 
 bool cont[MAX];
diff --git a/algorithms/graph/bipartite_match.cpp b/algorithms/graph/bipartite_match.cpp
index dde0774..92215e4 100644
--- a/algorithms/graph/bipartite_match.cpp
+++ b/algorithms/graph/bipartite_match.cpp
@@ -1,8 +1,8 @@
 /**
- * Bipartite Matching (simplified Ford-Fulkerson)
+ * Bipartite Matching
  *
- * Complexity (Time): O(n + m)
- * Complexity (Space): O(n + m)
+ * Complexity (Time): O(V + E)
+ * Complexity (Space): O(V + E)
  */
 
 vector<int> graph[MAX];
diff --git a/algorithms/graph/dfs.cpp b/algorithms/graph/dfs.cpp
index 6408d40..1dd2da5 100644
--- a/algorithms/graph/dfs.cpp
+++ b/algorithms/graph/dfs.cpp
@@ -1,8 +1,8 @@
 /**
  * Depth First Search (DFS)
  *
- * Complexity (Time): O(n + m)
- * Complexity (Space): O(n + m)
+ * Complexity (Time): O(V + E)
+ * Complexity (Space): O(V + E)
  */
 
 bool cont[MAX];
diff --git a/algorithms/graph/dijkstra.cpp b/algorithms/graph/dijkstra.cpp
index afb03e5..3328a27 100644
--- a/algorithms/graph/dijkstra.cpp
+++ b/algorithms/graph/dijkstra.cpp
@@ -1,8 +1,8 @@
 /**
  * Dijkstra
  *
- * Complexity (Time): O(m + n log n)
- * Complexity (Space): O(n + m)
+ * Complexity (Time): O(E + V log V)
+ * Complexity (Space): O(V + E)
  */
 
 int dist[MAX];
diff --git a/algorithms/graph/floyd_warshall.cpp b/algorithms/graph/floyd_warshall.cpp
index f913d87..8774a58 100644
--- a/algorithms/graph/floyd_warshall.cpp
+++ b/algorithms/graph/floyd_warshall.cpp
@@ -1,8 +1,8 @@
 /**
  * Floyd Warshall Algorithm
  *
- * Complexity (Time): O(n^3)
- * Complexity (Space): O(n^2)
+ * Complexity (Time): O(V^3)
+ * Complexity (Space): O(V^2)
  */
 
 int dist[MAX][MAX];
diff --git a/algorithms/graph/ford_fulkerson.cpp b/algorithms/graph/ford_fulkerson.cpp
new file mode 100644
index 0000000..87da194
--- /dev/null
+++ b/algorithms/graph/ford_fulkerson.cpp
@@ -0,0 +1,59 @@
+/**
+ * Ford-Fulkerson
+ * 
+ * Complexity (time): O(Ef)
+ * Complexity (space): O(V + E)
+ */
+
+int N;
+int par[MAX];
+int graph[MAX][MAX], rg[MAX][MAX];
+
+bool cont[MAX];
+
+// Finds if there's a path between s and t using non-full
+// residual edges
+bool path(int s, int t) {
+  cont[s] = true;
+  if (s == t)
+    return true;
+
+  for (int i = 0; i < N; ++i)
+    if (!cont[i] and rg[s][i]) {
+      par[i] = s;
+      if (path(i, t)) 
+        return true;
+    }
+
+  return false;
+}
+
+
+// Returns maximum flow between s (source) and t (sink)
+int ford_fulkerson(int s, int t) {
+  int ans = 0;
+  par[s] = -1;
+
+  mset(cont, 0);
+  memcpy(rg, graph, sizeof(graph));
+
+  // Repeat while there's a valid path between s and t
+  while (path(s, t)) {
+    int flow = inf;
+
+    // Get the minimum capacity among all edges of the chosen path
+    for (int i = t; par[i] != -1; i = par[i])
+      flow = min(f, rg[par[i]][i]);
+
+    // Update residual graph
+    for (int i = t; par[i] != -1; i = par[i]) {
+      rg[par[i]][i] -= flow;
+      rg[i][par[i]] += flow;
+    }
+
+    ans += flow;
+    mset(cont, 0);
+  }
+
+  return ans;
+}
diff --git a/algorithms/graph/kosaraju.cpp b/algorithms/graph/kosaraju.cpp
index b675ca5..486883b 100644
--- a/algorithms/graph/kosaraju.cpp
+++ b/algorithms/graph/kosaraju.cpp
@@ -1,8 +1,8 @@
 /**
  * Kosaraju
  *
- * Complexity (Time): O(n + m)
- * Complexity (Space): O(n + m)
+ * Complexity (Time): O(V + E)
+ * Complexity (Space): O(V + E)
  */
 
 stack<int> S;
diff --git a/algorithms/graph/kruskal.cpp b/algorithms/graph/kruskal.cpp
index 7cc272a..383808e 100644
--- a/algorithms/graph/kruskal.cpp
+++ b/algorithms/graph/kruskal.cpp
@@ -1,8 +1,8 @@
 /**
  * Kruskal
  *
- * Complexity (Time): O (m log n) 
- * Complexity (Space): O(m)
+ * Complexity (Time): O (E log V) 
+ * Complexity (Space): O(E)
  * 
  * #include <structure/disjoint_set>
  *
diff --git a/algorithms/graph/lca.cpp b/algorithms/graph/lca.cpp
index 8919ff7..32a2fce 100644
--- a/algorithms/graph/lca.cpp
+++ b/algorithms/graph/lca.cpp
@@ -2,9 +2,9 @@
  * Lowest Common Ancestor - LCA
  *
  * Complexity (Time):
- *   - preprocess: O(n log n)
- *   - query:      O(log n)
- * Complexity (Space): O(n + m + n log n)
+ *   - preprocess: O(V log V)
+ *   - query:      O(log V)
+ * Complexity (Space): O(V + E + V log V)
  *
  * OBS: *   = return sum path to LCA
  *      **  = return max value on path to LCA
diff --git a/algorithms/graph/prim.cpp b/algorithms/graph/prim.cpp
index 1229061..2270fa3 100644
--- a/algorithms/graph/prim.cpp
+++ b/algorithms/graph/prim.cpp
@@ -1,8 +1,8 @@
 /**
  * Prim
  *
- * Complexity (Time): O(m log m)
- * Complexity (Space): O(n + m)
+ * Complexity (Time): O(E log E)
+ * Complexity (Space): O(V + E)
  */
 
 bool cont[MAX];
diff --git a/algorithms/graph/tarjan.cpp b/algorithms/graph/tarjan.cpp
index bfcccdc..ede8a49 100644
--- a/algorithms/graph/tarjan.cpp
+++ b/algorithms/graph/tarjan.cpp
@@ -1,8 +1,8 @@
 /**
  * Tarjan - Strongly Connected Components
  *
- * Complexity (Time): O(n + m)
- * Complexity (Space): O(n + m)
+ * Complexity (Time): O(V + E)
+ * Complexity (Space): O(V + E)
  */
 
 vector<int> graph[MAX];
diff --git a/algorithms/graph/topological_sort.cpp b/algorithms/graph/topological_sort.cpp
index b4a7169..024828d 100644
--- a/algorithms/graph/topological_sort.cpp
+++ b/algorithms/graph/topological_sort.cpp
@@ -1,8 +1,8 @@
 /**
  * Topological Sort
  *
- * Complexity (Time): O(n + m)
- * Complexity (Space): O(n + m)
+ * Complexity (Time): O(V + E)
+ * Complexity (Space): O(V + E)
  */
 
 stack<int> S;
diff --git a/algorithms/structure/lazy_segment_tree.cpp b/algorithms/structure/lazy_segment_tree.cpp
index e53f12e..ea5c8a7 100644
--- a/algorithms/structure/lazy_segment_tree.cpp
+++ b/algorithms/structure/lazy_segment_tree.cpp
@@ -12,7 +12,7 @@ int N;
 int v[MAX];
 int tree[4 * MAX], lazy[4 * MAX];
 
-#define left(x) ((x << 1))
+#define left(x) (x << 1)
 #define right(x) ((x << 1) + 1)
 
 // Builds tree with elements from v (0-indexed)
diff --git a/algorithms/structure/segment_tree.cpp b/algorithms/structure/segment_tree.cpp
index 05d22eb..a579079 100644
--- a/algorithms/structure/segment_tree.cpp
+++ b/algorithms/structure/segment_tree.cpp
@@ -8,44 +8,54 @@
  * Complexity (Space): O(n)
  */
 
-int N, tree[4 * MAX], v[MAX];
+int N;
+int v[MAX];
+int tree[4 * MAX];
+
+#define left(x) (x << 1)
+#define right(x) ((x << 1) + 1)
 
 // Build tree with elements from v
-void build_tree(int node = 1, int a = 0, int b = N) {
-  if (a > b) return;
+void build(int node = 1, int a = 0, int b = N - 1) {
+  if (a > b) 
+    return;
 
   if (a == b) {
     tree[node] = v[a];
     return;
   }
 
-  build_tree(node * 2, a, (a + b) / 2);
-  build_tree(node * 2 + 1, 1 + (a + b) / 2, b);
+  build_tree(left(node), a, (a + b) / 2);
+  build_tree(right(node), 1 + (a + b) / 2, b);
   tree[node] = tree[node * 2] + tree[node * 2 + 1];
 }
 
 
 // Update position idx with value val
-void update_tree(int idx, int val, int node = 1, int a = 0, int b = N) {
-  if (a > b || a > idx || b < idx) return;
+void update(int idx, int val, int node = 1, int a = 0, int b = N - 1) {
+  if (a > b or a > idx or b < idx) 
+    return;
 
   if (a == b) {
     tree[node] = val;
     return;
   }
 
-  update_tree(idx, val, node * 2, a, (a + b) / 2);
-  update_tree(idx, val, node * 2 + 1, 1 + (a + b) / 2, b);
+  update_tree(idx, val, left(node), a, (a + b) / 2);
+  update_tree(idx, val, right(node), 1 + (a + b) / 2, b);
   tree[node] = tree[node * 2] + tree[node * 2 + 1];
 }
 
 
 // Return sum of [i,j]
-int query_tree(int i, int j, int node = 1, int a = 0, int b = N) {
-  if (a > b || a > j || b < i) return 0;
+int query(int i, int j, int node = 1, int a = 0, int b = N - 1) {
+  if (a > b or a > j or b < i) 
+    return 0;
 
-  if (a >= i && b <= j) return tree[node];
+  if (i <= a and b <= j) 
+    return tree[node];
 
-  return query_tree(i, j, node * 2, a, (a + b) / 2) + \
-         query_tree(i, j, node * 2 + 1, 1 + (a + b) / 2, b);
+  int q1 = query_tree(i, j, left(node), a, (a + b) / 2);
+  int q2 = query_tree(i, j, right(node), 1 + (a + b) / 2, b);
+  return q1 + q2;
 }
diff --git a/notebook/gen_latex.py b/notebook/gen_latex.py
index 03ffba5..ef9134f 100644
--- a/notebook/gen_latex.py
+++ b/notebook/gen_latex.py
@@ -8,8 +8,8 @@ from pathlib import Path
 dirs = [
     'algorithms',
     'misc',
-#    'contests',
-#    'problems'
+    'contests',
+    'problems'
 ]
 
 parser = argparse.ArgumentParser()
@@ -67,22 +67,21 @@ for di in dirs:
             if '*/' in line:
                 in_comment = False
 
-        in_ctime = False
+        if len(sections) > 2:
+            output.write('\\subsubsection{' + title + '}\n')
+
+        in_complexity = 0
         ctime, cspace = [], []
         for line in comment:
             if 'Complexity (time)' in line:
-                in_ctime = True
+                in_complexity = 1
             if 'Complexity (space)' in line:
-                in_ctime = False
+                in_complexity = 2
 
-            if in_ctime:
+            if in_complexity:
                 ctime.append(line)
 
 
-
-        if len(sections) > 2:
-            output.write('\\subsubsection{' + title + '}\n')
-
         # Remove first \n after header comment
         code = code[1:]
 
diff --git a/testing.py b/testing.py
new file mode 100644
index 0000000..74cd716
--- /dev/null
+++ b/testing.py
@@ -0,0 +1,53 @@
+from pathlib import Path
+
+dirs = [
+    'algorithms',
+    'misc',
+    'contests',
+    'problems'
+]
+
+def get_file_tree():
+    tree = {}
+    for di in dirs:
+        path_list = Path(di).glob('**/*.cpp')
+
+        for path in path_list:
+            branch = str(path).split('/')
+
+            curr = tree
+            for i in branch[:-2]:
+                if not i in curr:
+                    curr[i] = {}
+                curr = curr[i]
+
+            if not branch[-2] in curr:
+                curr[branch[-2]] = []
+            curr[branch[-2]].append(str(path))
+
+    return tree
+
+
+def gen_code_latex(arr, depth):
+    for i in arr:
+        print('\\' + depth + '{' + i + '}')
+
+def gen_latex(tree):
+    stack = [ (tree, 0) ]
+    depth = ['chapter', 'section', 'subsection']
+
+    while len(stack) != 0:
+        x, h = stack.pop()
+        if type(x) == list:
+            for i in x:
+                gen_code_latex(x, depth[h])
+
+        #print('\\' + depth[h] + '{' + i + '}')
+        for i in x:
+            stack.append((x[i], h + 1))
+    
+
+
+tree = get_file_tree()
+#print(tree)
+gen_latex(tree)
-- 
GitLab