TheAlgorithms/C++
1.0.0
All the algorithms implemented in C++
Loading...
Searching...
No Matches
lowest_common_ancestor.cpp
Go to the documentation of this file.
1
38
#include <cassert>
39
#include <iostream>
40
#include <queue>
41
#include <utility>
42
#include <vector>
43
48
namespace
graph
{
53
class
Graph
{
54
public
:
62
Graph
(
size_t
N,
const
std::vector<std::pair<int, int> > &undirected_edges) {
63
neighbors
.resize(N);
64
for
(
auto
&edge : undirected_edges) {
65
neighbors
[edge.first].push_back(edge.second);
66
neighbors
[edge.second].push_back(edge.first);
67
}
68
}
69
74
int
number_of_vertices
()
const
{
return
neighbors
.size(); }
75
77
std::vector<std::vector<int> >
neighbors
;
78
};
79
84
class
RootedTree
:
public
Graph
{
85
public
:
93
RootedTree
(
const
std::vector<std::pair<int, int> > &undirected_edges,
94
int
root_)
95
:
Graph
(undirected_edges.size() + 1, undirected_edges),
root
(root_) {
96
populate_parents
();
97
}
98
104
std::vector<int>
parent
;
106
std::vector<int>
level
;
108
int
root
;
109
110
protected
:
117
void
populate_parents
() {
118
// Initialize the vector with -1 which indicates the vertex
119
// wasn't yet visited.
120
parent
= std::vector<int>(
number_of_vertices
(), -1);
121
level
= std::vector<int>(
number_of_vertices
());
122
parent
[
root
] =
root
;
123
level
[
root
] = 0;
124
std::queue<int> queue_of_vertices;
125
queue_of_vertices.push(
root
);
126
while
(!queue_of_vertices.empty()) {
127
int
vertex = queue_of_vertices.front();
128
queue_of_vertices.pop();
129
for
(
int
neighbor :
neighbors
[vertex]) {
130
// As long as the vertex was not yet visited.
131
if
(
parent
[neighbor] == -1) {
132
parent
[neighbor] = vertex;
133
level
[neighbor] =
level
[vertex] + 1;
134
queue_of_vertices.push(neighbor);
135
}
136
}
137
}
138
}
139
};
140
145
class
LowestCommonAncestor
{
146
public
:
151
explicit
LowestCommonAncestor
(
const
RootedTree
&tree_) : tree(tree_) {
152
populate_up
();
153
}
154
164
int
lowest_common_ancestor
(
int
u,
int
v)
const
{
165
// Ensure u is the deeper (higher level) of the two vertices
166
if
(tree.
level
[v] > tree.
level
[u]) {
167
std::swap(u, v);
168
}
169
170
// "Lift" u to the same level as v.
171
int
level_diff = tree.
level
[u] - tree.
level
[v];
172
for
(
int
i = 0; (1 << i) <= level_diff; ++i) {
173
if
(level_diff & (1 << i)) {
174
u =
up
[u][i];
175
}
176
}
177
assert(tree.
level
[u] == tree.
level
[v]);
178
179
if
(u == v) {
180
return
u;
181
}
182
183
// "Lift" u and v to their 2^i th ancestor if they are different
184
for
(
int
i =
static_cast<
int
>
(
up
[u].size()) - 1; i >= 0; --i) {
185
if
(
up
[u][i] !=
up
[v][i]) {
186
u =
up
[u][i];
187
v =
up
[v][i];
188
}
189
}
190
191
// As we regressed u an v such that they cannot further be lifted so
192
// that their ancestor would be different, the only logical
193
// consequence is that their parent is the sought answer.
194
assert(
up
[u][0] ==
up
[v][0]);
195
return
up
[u][0];
196
}
197
198
/* \brief reference to the rooted tree this structure allows to query */
199
const
RootedTree
&tree;
206
std::vector<std::vector<int> >
up
;
207
208
protected
:
212
void
populate_up
() {
213
up
.resize(tree.
number_of_vertices
());
214
for
(
int
vertex = 0; vertex < tree.
number_of_vertices
(); ++vertex) {
215
up
[vertex].push_back(tree.
parent
[vertex]);
216
}
217
for
(
int
level = 0; (1 << level) < tree.
number_of_vertices
(); ++level) {
218
for
(
int
vertex = 0; vertex < tree.
number_of_vertices
(); ++vertex) {
219
// up[vertex][level + 1] = 2^(level + 1) th ancestor of vertex =
220
// = 2^level th ancestor of 2^level th ancestor of vertex =
221
// = 2^level th ancestor of up[vertex][level]
222
up
[vertex].push_back(
up
[
up
[vertex][level]][level]);
223
}
224
}
225
}
226
};
227
228
}
// namespace graph
229
234
static
void
tests
() {
244
std::vector<std::pair<int, int> > edges = {
245
{7, 1}, {1, 5}, {1, 3}, {3, 6}, {6, 2}, {2, 9}, {6, 8}, {4, 3}, {0, 4}};
246
graph::RootedTree
t(edges, 3);
247
graph::LowestCommonAncestor
lca(t);
248
assert(lca.
lowest_common_ancestor
(7, 4) == 3);
249
assert(lca.
lowest_common_ancestor
(9, 6) == 6);
250
assert(lca.
lowest_common_ancestor
(0, 0) == 0);
251
assert(lca.
lowest_common_ancestor
(8, 2) == 6);
252
}
253
255
int
main
() {
256
tests
();
257
return
0;
258
}
graph::Graph
Definition
lowest_common_ancestor.cpp:53
graph::Graph::neighbors
std::vector< std::vector< int > > neighbors
for each vertex it stores a list indicies of its neighbors
Definition
lowest_common_ancestor.cpp:77
graph::Graph::Graph
Graph(size_t N, const std::vector< std::pair< int, int > > &undirected_edges)
Populate the adjacency list for each vertex in the graph. Assumes that evey edge is a pair of valid v...
Definition
lowest_common_ancestor.cpp:62
graph::Graph::number_of_vertices
int number_of_vertices() const
Definition
lowest_common_ancestor.cpp:74
graph::LowestCommonAncestor
Definition
lowest_common_ancestor.cpp:145
graph::LowestCommonAncestor::populate_up
void populate_up()
Definition
lowest_common_ancestor.cpp:212
graph::LowestCommonAncestor::up
std::vector< std::vector< int > > up
for every vertex stores a list of its ancestors by powers of two For each vertex, the first element o...
Definition
lowest_common_ancestor.cpp:206
graph::LowestCommonAncestor::lowest_common_ancestor
int lowest_common_ancestor(int u, int v) const
Query the structure to find the lowest common ancestor. Assumes that the provided numbers are valid i...
Definition
lowest_common_ancestor.cpp:164
graph::LowestCommonAncestor::LowestCommonAncestor
LowestCommonAncestor(const RootedTree &tree_)
Stores the tree and precomputs "up lifts".
Definition
lowest_common_ancestor.cpp:151
graph::RootedTree
Definition
lowest_common_ancestor.cpp:84
graph::RootedTree::level
std::vector< int > level
Stores the distance from the root.
Definition
lowest_common_ancestor.cpp:106
graph::RootedTree::parent
std::vector< int > parent
Stores parent of every vertex and for root its own index. The root is technically not its own parent,...
Definition
lowest_common_ancestor.cpp:104
graph::RootedTree::RootedTree
RootedTree(const std::vector< std::pair< int, int > > &undirected_edges, int root_)
Constructs the tree by calculating parent for every vertex. Assumes a valid description of a tree is ...
Definition
lowest_common_ancestor.cpp:93
graph::RootedTree::root
int root
Index of the root vertex.
Definition
lowest_common_ancestor.cpp:108
graph::RootedTree::populate_parents
void populate_parents()
Calculate the parents for all the vertices in the tree. Implements the breadth first search algorithm...
Definition
lowest_common_ancestor.cpp:117
tests
static void tests()
Definition
lowest_common_ancestor.cpp:234
main
int main()
Definition
lowest_common_ancestor.cpp:255
graph
Graph Algorithms.
graph
lowest_common_ancestor.cpp
Generated by
1.12.0