100#include <tclap/CmdLine.h>
103using namespace Aleph;
235 for (
auto it = g.
get_node_it(); it.has_curr(); it.next())
236 if (it.get_curr()->get_info() == name)
237 return it.get_curr();
246 cout <<
"\n=== " << title <<
" ===" <<
endl;
250 cout <<
"\nConnections:" <<
endl;
253 auto* node =
nit.get_curr();
254 cout <<
" " << node->get_info() <<
" -- ";
259 auto* arc =
ait.get_curr();
261 if (
not first) cout <<
", ";
262 cout << neighbor->get_info();
274 cout <<
"\n--- Finding Cut Nodes (Articulation Points) ---" <<
endl;
284 cout <<
"\nNo cut nodes found - graph is biconnected!" <<
endl;
285 cout <<
"Removing any single node won't disconnect the graph." <<
endl;
289 cout <<
"\nCut nodes found: " << cut_nodes.
size() <<
endl;
290 cout <<
"Cut nodes: ";
292 for (
auto it = cut_nodes.
get_it(); it.has_curr(); it.next())
294 if (
not first) cout <<
", ";
295 cout << it.get_curr()->get_info();
300 cout <<
"\nImpact: Removing any of these nodes disconnects the graph." <<
endl;
309 cout <<
"\n" << string(60,
'=') <<
endl;
310 cout <<
"Practical Example: Network Vulnerability Analysis" <<
endl;
311 cout << string(60,
'=') <<
endl;
321 cout <<
"\n--- Vulnerability Analysis ---" <<
endl;
325 cout <<
"Network is fully redundant - no single point of failure!" <<
endl;
329 cout <<
"Single points of failure identified:" <<
endl;
330 for (
auto it = cut_nodes.
get_it(); it.has_curr(); it.next())
332 auto* node = it.get_curr();
333 cout <<
"\n * " << node->get_info() <<
endl;
341 cout <<
" Risk: CRITICAL - failure would partition the network" <<
endl;
345 cout <<
"\n--- Recommendations ---" <<
endl;
346 cout <<
"1. Add redundant links to eliminate cut nodes" <<
endl;
347 cout <<
"2. Prioritize backup for critical equipment" <<
endl;
348 cout <<
"3. Monitor cut nodes for failures" <<
endl;
356 cout <<
"\n" << string(60,
'=') <<
endl;
357 cout <<
"Biconnected Components" <<
endl;
358 cout << string(60,
'=') <<
endl;
368 cout <<
"\nCut nodes: ";
369 for (
auto it = cut_nodes.
get_it(); it.has_curr(); it.next())
370 cout << it.get_curr()->get_info() <<
" ";
377 cout <<
"\n--- Biconnected Components ---" <<
endl;
380 cout <<
"\nNodes by component (color):" <<
endl;
383 cout <<
" Component " <<
color <<
": ";
387 auto* node =
nit.get_curr();
390 if (
not first) cout <<
", ";
391 cout << node->get_info();
398 cout <<
"\n--- Analysis ---" <<
endl;
399 cout <<
"A biconnected component has no cut nodes within it." <<
endl;
400 cout <<
"Components are connected through cut nodes." <<
endl;
408 cout <<
"\n" << string(60,
'=') <<
endl;
409 cout <<
"Network Resilience Comparison" <<
endl;
410 cout << string(60,
'=') <<
endl;
413 cout <<
"\n--- Fragile Network (Tree-like) ---" <<
endl;
420 compute(
fragile.get_first_node(), cut_nodes);
422 cout <<
"Cut nodes: " << cut_nodes.
size() <<
" out of "
425 cout <<
"Fragility score: " << fixed << setprecision(1) <<
fragility <<
"%" <<
endl;
429 cout <<
"\n--- Resilient Network (With Cycles) ---" <<
endl;
436 compute(
resilient.get_first_node(), cut_nodes);
438 cout <<
"Cut nodes: " << cut_nodes.
size() <<
" out of "
441 cout <<
"Fragility score: " << fixed << setprecision(1) <<
fragility <<
"%" <<
endl;
444 cout <<
"\n--- Key Insight ---" <<
endl;
445 cout <<
"Adding redundant connections (creating cycles) reduces fragility" <<
endl;
446 cout <<
"by eliminating articulation points." <<
endl;
459 cout <<
"\n" << string(60,
'=') <<
endl;
460 cout <<
"Bridge Edges (Isthmuses / Cut Edges)" <<
endl;
461 cout << string(60,
'=') <<
endl;
462 cout <<
"A bridge is an edge whose removal disconnects the graph." <<
endl;
463 cout <<
"Algorithm: Tarjan low-link DFS — O(V + E)." <<
endl;
467 cout <<
"\n--- Scenario 1: Computer Network ---" <<
endl;
475 cout <<
"\nBridge edges (" <<
bridges.size() <<
" found):" <<
endl;
477 cout <<
" (none — graph is 2-edge-connected)" <<
endl;
483 <<
" ← bridge" <<
endl;
486 cout <<
"\nImpact: severing a bridge immediately splits the network." <<
endl;
491 cout <<
"\n--- Scenario 2: Ring Topology (no bridges) ---" <<
endl;
507 cout <<
"Ring A-B-C-D-E-A: ";
509 cout <<
"no bridges (fully 2-edge-connected)." <<
endl;
511 cout <<
bridges.size() <<
" bridge(s) found." <<
endl;
516 cout <<
"\n--- Scenario 3: Two Triangles + Bridge ---" <<
endl;
517 cout <<
" Triangle1: A-B-C-A Bridge: C--D Triangle2: D-E-F-D" <<
endl;
529 cout <<
"\nBridges found: " <<
bridges.size() <<
endl;
539 cout <<
"\nArticulation points (cut nodes): ";
541 { cout << p->get_info() <<
" "; });
543 cout <<
"Note: bridge endpoints C and D are also articulation points." <<
endl;
552 cout <<
"\n" << string(60,
'=') <<
endl;
553 cout <<
"Fixing Network Vulnerabilities" <<
endl;
554 cout << string(60,
'=') <<
endl;
558 cout <<
"\n--- Before: Original Network ---" <<
endl;
565 cout <<
"Cut nodes: ";
566 for (
auto it = cut_nodes.
get_it(); it.has_curr(); it.next())
567 cout << it.get_curr()->get_info() <<
" ";
571 cout <<
"\n--- Adding Redundant Links ---" <<
endl;
579 cout <<
"Adding link: C -- D" <<
endl;
582 cout <<
"Adding link: A -- F" <<
endl;
585 cout <<
"\n--- After: Reinforced Network ---" <<
endl;
593 cout <<
"No cut nodes! Network is now more resilient." <<
endl;
596 cout <<
"Remaining cut nodes: ";
597 for (
auto it = cut_nodes.
get_it(); it.has_curr(); it.next())
598 cout << it.get_curr()->get_info() <<
" ";
603 cout <<
"\n--- Lesson ---" <<
endl;
604 cout <<
"Strategic addition of edges can eliminate articulation points" <<
endl;
605 cout <<
"and improve network reliability." <<
endl;
612 TCLAP::CmdLine
cmd(
"Cut Nodes (Articulation Points) Example",
' ',
"1.0");
614 TCLAP::SwitchArg
basicArg(
"b",
"basic",
615 "Show basic cut nodes demo",
false);
616 TCLAP::SwitchArg
netArg(
"n",
"network",
617 "Show network vulnerability analysis",
false);
618 TCLAP::SwitchArg
biconArg(
"c",
"biconnected",
619 "Show biconnected components",
false);
620 TCLAP::SwitchArg
compareArg(
"r",
"resilience",
621 "Compare network resilience",
false);
622 TCLAP::SwitchArg
fixArg(
"f",
"fix",
623 "Show fixing vulnerabilities",
false);
625 "Show bridge edges demo",
false);
626 TCLAP::SwitchArg
allArg(
"a",
"all",
627 "Run all demos",
false);
651 cout <<
"=== Cut Nodes, Bridges, and Biconnected Components ===" <<
endl;
652 cout <<
"Cut node removal / bridge removal disconnects the graph." <<
endl;
676 cout <<
"\n=== Summary ===" <<
endl;
677 cout <<
"Cut nodes and bridges are dual notions of graph vulnerability:" <<
endl;
678 cout <<
" cut node = vertex whose removal disconnects the graph" <<
endl;
679 cout <<
" bridge = edge whose removal disconnects the graph" <<
endl;
680 cout <<
"Both detected by Tarjan low-link DFS in O(V + E)." <<
endl;
681 cout <<
"Headers: tpl_cut_nodes.H (Compute_Cut_Nodes, Compute_Bridges," <<
endl;
682 cout <<
" compute_cut_nodes(), find_bridges())" <<
endl;
686 catch (TCLAP::ArgException& e)
688 cerr <<
"Error: " << e.error() <<
" for arg " << e.argId() <<
endl;
WeightedDigraph::Node Node
Find bridge edges (isthmuses) of a connected undirected graph.
Computation of cut nodes (articulation points) of a graph.
long paint_subgraphs()
Paints the connected components around the cut nodes.
constexpr bool is_empty() const noexcept
Return true if this (as header node) is empty.
Dynamic doubly linked list with O(1) size and bidirectional access.
const size_t & size() const noexcept
Return the number of elements (constant time)
void next()
Advances the iterator to the next filtered element.
Node * get_first_node() const
Return any node in the graph.
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Arc Arc
The node class type.
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Node * get_connected_node(Arc *arc, Node *node) const noexcept
Return the adjacent node to node through arc.
long & get_counter(Node *node) const noexcept
Get a modifiable reference to the counter of node
constexpr size_t get_num_arcs() const noexcept
auto get_node_it() const noexcept
Obtains an iterator to the nodes of graph.
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Graph build_computer_network()
Build a graph representing a computer network.
Graph build_network_graph()
Build a network with clear cut nodes.
void demo_biconnected_components()
Demonstrate biconnected components.
void print_graph(Graph &g, const string &title)
Print graph structure.
Graph build_cyclic_graph()
Build a cyclic graph with fewer cut nodes.
void demo_fixing_vulnerabilities()
Demonstrate fixing network vulnerabilities.
void demo_network_vulnerability()
Practical example: Network vulnerability analysis.
void demo_resilience_comparison()
Compare resilient vs fragile networks.
Graph::Node * find_node(Graph &g, const string &name)
Find a node by name.
void demo_bridges()
Demonstrate bridge finding with Compute_Bridges / find_bridges().
void demo_cut_nodes(Graph &g, const string &description)
Demonstrate finding cut nodes.
DynList< typename GT::Node * > compute_cut_nodes(const GT &g, typename GT::Node *start)
Compute articulation points (cut vertices) of an undirected graph.
DynList< typename GT::Arc * > find_bridges(const GT &g, typename GT::Node *start, SA sa=SA())
Find all bridge edges in a connected undirected graph.
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
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.
static long & color(typename GT::Node *p)
Arc of graph implemented with double-linked adjacency lists.
Node belonging to a graph implemented with a double linked adjacency list.
Filtered iterator of adjacent arcs of a node.
Articulation points (cut nodes), bridges, and biconnected components.
Generic graph and digraph implementations.