#include <bits/stdc++.h>
#define V 5 // number of nodes in input tree
#define WHITE 1 // COLOUR 'WHITE' is assigned value 1
#define BLACK 2 // COLOUR 'BLACK' is assigned value 2
struct
Node
{
int
data;
Node* left, *right;
};
struct
subset
{
int
parent, rank, ancestor, child, sibling, color;
};
struct
Query
{
int
L, R;
};
Node* newNode(
int
data)
{
Node* node =
new
Node;
node->data = data;
node->left = node->right = NULL;
return
(node);
}
void
makeSet(
struct
subset subsets[],
int
i)
{
if
(i < 1 || i > V)
return
;
subsets[i].color = WHITE;
subsets[i].parent = i;
subsets[i].rank = 0;
return
;
}
int
findSet(
struct
subset subsets[],
int
i)
{
if
(subsets[i].parent != i)
subsets[i].parent = findSet (subsets, subsets[i].parent);
return
subsets[i].parent;
}
void
unionSet(
struct
subset subsets[],
int
x,
int
y)
{
int
xroot = findSet (subsets, x);
int
yroot = findSet (subsets, y);
if
(subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else
if
(subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
else
{
subsets[yroot].parent = xroot;
(subsets[xroot].rank)++;
}
}
void
lcaWalk(
int
u,
struct
Query q[],
int
m,
struct
subset subsets[])
{
makeSet(subsets, u);
subsets[findSet(subsets, u)].ancestor = u;
int
child = subsets[u].child;
while
(child != 0)
{
lcaWalk(child, q, m, subsets);
unionSet (subsets, u, child);
subsets[findSet(subsets, u)].ancestor = u;
child = subsets[child].sibling;
}
subsets[u].color = BLACK;
for
(
int
i = 0; i < m; i++)
{
if
(q[i].L == u)
{
if
(subsets[q[i].R].color == BLACK)
{
printf
(
"LCA(%d %d) -> %d\n"
,
q[i].L,
q[i].R,
subsets[findSet(subsets,q[i].R)].ancestor);
}
}
else
if
(q[i].R == u)
{
if
(subsets[q[i].L].color == BLACK)
{
printf
(
"LCA(%d %d) -> %d\n"
,
q[i].L,
q[i].R,
subsets[findSet(subsets,q[i].L)].ancestor);
}
}
}
return
;
}
void
preprocess(Node * node,
struct
subset subsets[])
{
if
(node == NULL)
return
;
preprocess(node->left, subsets);
if
(node->left != NULL&&node->right != NULL)
{
subsets[node->data].child = node->left->data;
subsets[node->left->data].sibling =
node->right->data;
}
else
if
((node->left != NULL && node->right == NULL)
|| (node->left == NULL && node->right != NULL))
{
if
(node->left != NULL && node->right == NULL)
subsets[node->data].child = node->left->data;
else
subsets[node->data].child = node->right->data;
}
preprocess (node->right, subsets);
}
void
initialise(
struct
subset subsets[])
{
memset
(subsets, 0, (V+1) *
sizeof
(
struct
subset));
for
(
int
i=1; i<=V; i++)
subsets[i].color=WHITE;
return
;
}
void
printLCAs(Node *root, Query q[],
int
m)
{
struct
subset * subsets =
new
subset[V+1];
initialise(subsets);
preprocess(root, subsets);
lcaWalk(root->data , q, m, subsets);
}
int
main()
{
Node *root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
Query q[] = {{5, 4}, {1, 3}, {2, 3}};
int
m =
sizeof
(q)/
sizeof
(q[0]);
printLCAs(root, q, m);
return
0;
}