Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
hld_example.cc
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
31
42#include <array>
43#include <cstddef>
44#include <iomanip>
45#include <iostream>
46#include <string>
47
48#include <HLD.H>
49#include <tpl_array.H>
50#include <tpl_graph.H>
51
52using namespace Aleph;
53
54namespace
55{
57 using Node = G::Node;
58
59 // ================================================================
60 // Scenario 1: Corporate Hierarchy — Security Clearance (Path Max)
70 {
71 std::cout << "============================================================\n";
72 std::cout << " Scenario 1: Corporate Hierarchy — Security Clearance\n";
73 std::cout << "============================================================\n\n";
74 std::cout << " Find the highest security clearance on the path between\n";
75 std::cout << " two employees in the org chart.\n\n";
76
77 // Org chart:
78 // CEO(0) clearance=5
79 // / |
80 // CTO(1) CFO(2) clearance=4, 3
81 // / | / |
82 // Eng(3) Data(4) Acct(5) Legal(6) clearance=2,3,1,2
83 // |
84 // ML(7) clearance=3
85
86 G g;
87 auto n = Array<Node *>::create(8);
88 for (size_t i = 0; i < 8; ++i)
89 n(i) = g.insert_node(static_cast<int>(i));
90
91 g.insert_arc(n(0), n(1), 1);
92 g.insert_arc(n(0), n(2), 1);
93 g.insert_arc(n(1), n(3), 1);
94 g.insert_arc(n(1), n(4), 1);
95 g.insert_arc(n(2), n(5), 1);
96 g.insert_arc(n(2), n(6), 1);
97 g.insert_arc(n(4), n(7), 1);
98
99 constexpr std::array<const char *, 8> names = {
100 "CEO", "CTO", "CFO", "Eng", "Data", "Acct", "Legal", "ML"};
101 constexpr std::array<int, 8> clearance = {5, 4, 3, 2, 3, 1, 2, 3};
102
103 auto nv = [&clearance](Node * p) { return clearance[static_cast<size_t>(p->get_info())]; };
104 HLD_Max<G, int> hld(g, n(0), nv);
105
106 struct Query { size_t u, v; };
107 constexpr Query queries[] = {{3, 7}, {5, 7}, {3, 6}, {7, 7}};
108
109 std::cout << std::left
110 << std::setw(20) << "Query(u,v)"
111 << std::setw(12) << "Max Clear."
112 << std::setw(12) << "Distance"
113 << "LCA\n";
114 std::cout << std::string(54, '-') << "\n";
115
116 for (const auto & q : queries)
117 {
118 const int mx = hld.path_query(n(q.u), n(q.v));
119 const size_t dist = hld.distance(n(q.u), n(q.v));
120 auto * l = hld.lca(n(q.u), n(q.v));
121 const auto lid = static_cast<size_t>(l->get_info());
122
123 std::cout << std::left
124 << std::setw(20)
125 << (std::string(names[q.u]) + "," + names[q.v])
126 << std::setw(12) << mx
127 << std::setw(12) << dist
128 << names[lid] << "\n";
129 }
130
131 std::cout << "\nHLD chains: " << hld.num_chains() << "\n\n";
132 }
133
134 // ================================================================
135 // Scenario 2: Network — Bandwidth Bottleneck (Path Min)
147 {
148 std::cout << "============================================================\n";
149 std::cout << " Scenario 2: Network — Bandwidth Bottleneck\n";
150 std::cout << "============================================================\n\n";
151 std::cout << " Find the minimum bandwidth (bottleneck) on the path\n";
152 std::cout << " between two servers in a tree network.\n";
153 std::cout << " Edge weights stored on child nodes.\n\n";
154
155 // Network tree:
156 // Router(0) bw=0 (root, unused)
157 // / | |
158 // S1(1) S2(2) S3(3) bw=100, 50, 80 (link to router)
159 // / |
160 // S4(4) S5(5) bw=30, 60 (link to parent)
161 // |
162 // S6(6) bw=90
163
164 G g;
165 auto n = Array<Node *>::create(7);
166 for (size_t i = 0; i < 7; ++i)
167 n(i) = g.insert_node(static_cast<int>(i));
168
169 g.insert_arc(n(0), n(1), 1);
170 g.insert_arc(n(0), n(2), 1);
171 g.insert_arc(n(0), n(3), 1);
172 g.insert_arc(n(1), n(4), 1);
173 g.insert_arc(n(2), n(5), 1);
174 g.insert_arc(n(4), n(6), 1);
175
176 constexpr std::array<const char *, 7> names = {
177 "Router", "S1", "S2", "S3", "S4", "S5", "S6"};
178 constexpr std::array<int, 7> bandwidth = {1000, 100, 50, 80, 30, 60, 90};
179
180 auto nv = [&bandwidth](Node * p) { return bandwidth[static_cast<size_t>(p->get_info())]; };
181 HLD_Min<G, int> hld(g, n(0), nv);
182
183 struct Query { size_t u, v; };
184 constexpr Query queries[] = {{6, 5}, {4, 3}, {6, 3}, {1, 2}};
185
186 std::cout << std::left
187 << std::setw(16) << "Path"
188 << std::setw(18) << "Bottleneck(edge)"
189 << "Distance\n";
190 std::cout << std::string(44, '-') << "\n";
191
192 for (const auto & q : queries)
193 {
194 // Edge-weighted: skip LCA node
195 const int bw = hld.path_query_edges(n(q.u), n(q.v));
196 const size_t dist = hld.distance(n(q.u), n(q.v));
197
198 std::cout << std::left
199 << std::setw(16)
200 << (std::string(names[q.u]) + " -> " + names[q.v])
201 << std::setw(18) << bw
202 << dist << " hops\n";
203 }
204
205 std::cout << "\n";
206 }
207
208 // ================================================================
209 // Scenario 3: Tax Routes — Path Sum + Dynamic Updates
222 {
223 std::cout << "============================================================\n";
224 std::cout << " Scenario 3: Tax Routes — Sum + Dynamic Updates\n";
225 std::cout << "============================================================\n\n";
226 std::cout << " Sum taxes on a trade route (path between cities).\n";
227 std::cout << " Update taxes after policy change.\n\n";
228
229 // Capital(0) tax=10
230 // / |
231 // Port(1) Market(2) tax=5, 8
232 // / | |
233 // Farm(3) Mine(4) Workshop(5) tax=3, 7, 6
234
235 G g;
236 auto n = Array<Node *>::create(6);
237 for (size_t i = 0; i < 6; ++i)
238 n(i) = g.insert_node(static_cast<int>(i));
239
240 g.insert_arc(n(0), n(1), 1);
241 g.insert_arc(n(0), n(2), 1);
242 g.insert_arc(n(1), n(3), 1);
243 g.insert_arc(n(1), n(4), 1);
244 g.insert_arc(n(2), n(5), 1);
245
246 constexpr std::array<const char *, 6> names = {
247 "Capital", "Port", "Market", "Farm", "Mine", "Workshop"};
248 constexpr std::array<int, 6> taxes = {10, 5, 8, 3, 7, 6};
249
250 auto nv = [&taxes](Node * p) { return taxes[static_cast<size_t>(p->get_info())]; };
251 HLD_Sum<G, int> hld(g, n(0), nv);
252
253 auto print_query = [&](const char * label, size_t u, size_t v)
254 {
255 std::cout << " " << std::left << std::setw(25) << label
256 << "path_sum(" << names[u] << ", " << names[v] << ") = "
257 << hld.path_query(n(u), n(v)) << "\n";
258 };
259
260 std::cout << "Before policy change:\n";
261 print_query("Farm->Workshop", 3, 5);
262 print_query("Mine->Workshop", 4, 5);
263 print_query("Farm->Mine", 3, 4);
264
265 std::cout << "\n subtree_sum(Port) = "
266 << hld.subtree_query(n(1)) << "\n";
267 std::cout << " subtree_sum(Capital) = "
268 << hld.subtree_query(n(0)) << "\n";
269
270 // Policy change: Capital tax doubles
271 std::cout << "\nPolicy change: Capital tax 10 -> 20\n";
272 hld.point_update(n(0), 20);
273
274 std::cout << "\nAfter policy change:\n";
275 print_query("Farm->Workshop", 3, 5);
276 print_query("Mine->Workshop", 4, 5);
277
278 std::cout << "\n subtree_sum(Capital) = "
279 << hld.subtree_query(n(0)) << "\n";
280
281 // Another update
282 std::cout << "\nNew tax-free zone at Port (5 -> 0):\n";
283 hld.point_update(n(1), 0);
284
285 print_query("Farm->Workshop", 3, 5);
286 std::cout << " subtree_sum(Port) = "
287 << hld.subtree_query(n(1)) << "\n";
288
289 std::cout << "\n";
290 }
291}
292
293
303int main()
304{
305 std::cout << "==============================================================\n";
306 std::cout << " Heavy-Light Decomposition on Aleph Tree Graphs\n";
307 std::cout << "==============================================================\n\n";
308
312
313 std::cout << "All scenarios completed successfully.\n";
314
315 return 0;
316}
Heavy-Light Decomposition for tree path queries on Aleph graphs.
WeightedDigraph::Node Node
static Array create(size_t n)
Create an array with n logical elements.
Definition tpl_array.H:194
Graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:428
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Definition tpl_graph.H:524
_Graph_Node Node
The graph type.
Definition tpl_graph.H:432
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Definition tpl_graph.H:604
int main()
Entry point that runs HLD demonstration scenarios for Aleph tree graphs.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
Arc of graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:222
HLD with path/subtree max queries.
Definition HLD.H:969
HLD with path/subtree min queries.
Definition HLD.H:996
HLD with path/subtree sum queries.
Definition HLD.H:942
Dynamic array container with automatic resizing.
Generic graph and digraph implementations.
DynList< int > l