From a7543847a9f12df6470734d341cae79ea10dc596 Mon Sep 17 00:00:00 2001
From: Bruno Freitas Tissei <bft15@inf.ufpr.br>
Date: Sat, 3 Feb 2018 11:26:22 -0200
Subject: [PATCH] Add LCA

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

diff --git a/graph/lca.cpp b/graph/lca.cpp
new file mode 100644
index 0000000..f441761
--- /dev/null
+++ b/graph/lca.cpp
@@ -0,0 +1,78 @@
+/**
+ * Lowest Common Ancestor - LCA
+ *
+ * Complexity (Time): 
+ *   preprocess -> O(n log n)
+ *   query      -> O(log n)
+ * Complexity (Space): O(n + m + n log n)
+ * 
+ *
+ * OBS: *  = return sum path to LCA
+ *      ** = return max value on path to LCA
+ */
+
+vector<ii> graph[MAX];
+
+int h[MAX];
+int par[MAX][MAXLOG], cost[MAX][MAXLOG];
+
+// Perform DFS while filling h, par, and cost
+void dfs(int v, int p = -1, int c = 0) {
+	par[v][0] = p;
+  //*** cost[v][0] = c;
+
+	if (p + 1)
+		h[v] = h[p] + 1;
+
+	for (int i = 1; i < MAXLOG; i++)
+		if (par[v][i - 1] + 1) {
+			par[v][i] = par[par[v][i - 1]][i - 1];
+      //*** cost[v][i] += cost[v][i - 1] + cost[par[v][i - 1]][i - 1];
+    }
+
+	for (auto u : graph[v])	
+    if (p != u.fi)
+		  dfs(u.fi, v, u.se);
+}
+
+// Preprocess tree with rooted at v
+void preprocess(int v) {
+  memset(par, -1, sizeof par);
+  memset(cost, 0, sizeof cost);
+  dfs(v);
+}
+
+// Return LCA between p and q
+int query(int p, int q) {
+  //*** int ans = 0;
+
+  if (h[p] < h[q])
+    swap(p, q);
+
+  for (int i = MAXLOG - 1; i >= 0; i--)
+    if (par[p][i] + 1 && h[par[p][i]] >= h[q]) {
+      //* ans += cost[p][i];
+      //** ans = max(ans, cost[p][i]);
+      p = par[p][i];
+    }
+
+  if (p == q)
+    return p;
+    //*** return ans;
+
+  for (int i = MAXLOG - 1; i >= 0; i--)
+    if (par[p][i] + 1 && par[p][i] != par[q][i]) {
+      //* ans += cost[p][i] + cost[q][i];
+      //** ans = max(ans, max(cost[p][i], cost[q][i]));
+      p = par[p][i];
+      q = par[q][i];
+    }
+
+  return dp[p][0];
+
+  //* if (p == q) return ans;
+  //* else return ans + cost[p][0] + cost[q][0];
+
+  //** if (p == q) return ans;
+  //** else return max(ans, max(cost[p][0], cost[q][0]));
+}
-- 
GitLab