2
\file lib/vector/neta/bridge.c
4
\brief Network Analysis library - bridges
6
Computes number of bridges in the graph.
8
(C) 2009-2010 by Daniel Bundala, and the GRASS Development Team
10
This program is free software under the GNU General Public License
11
(>=v2). Read the file COPYING that comes with GRASS for details.
13
\author Daniel Bundala (Google Summer of Code 2009)
18
#include <grass/gis.h>
19
#include <grass/vector.h>
20
#include <grass/glocale.h>
21
#include <grass/dgl/graph.h>
24
\brief Get number of bridges in the graph.
26
Bridge is an array containing the indices of the bridges.
28
\param graph input graph
29
\param[out] bridge_list list of bridges
31
\return number of bridges, -1 on error
33
int NetA_compute_bridges(dglGraph_s * graph, struct ilist *bridge_list)
38
dglEdgesetTraverser_s *current; /*edge to be processed when the node is visited */
39
int *tin, *min_tin; /*time in, and smallest tin over all successors. 0 if not yet visited */
40
dglInt32_t *parent; /*edge from parent to the node */
41
dglInt32_t **stack; /*stack of nodes */
42
dglInt32_t **current_edge; /*current edge for each node */
43
dglNodeTraverser_s nt;
44
dglInt32_t *current_node;
48
nnodes = dglGet_NodeCount(graph);
50
(dglEdgesetTraverser_s *) G_calloc(nnodes + 1,
51
sizeof(dglEdgesetTraverser_s));
52
tin = (int *)G_calloc(nnodes + 1, sizeof(int));
53
min_tin = (int *)G_calloc(nnodes + 1, sizeof(int));
54
parent = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t));
55
stack = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *));
56
current_edge = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *));
57
if (!tin || !min_tin || !parent || !stack || !current) {
58
G_fatal_error(_("Out of memory"));
62
for (i = 1; i <= nnodes; i++) {
63
dglEdgeset_T_Initialize(¤t[i], graph,
64
dglNodeGet_OutEdgeset(graph,
65
dglGetNode(graph, i)));
66
current_edge[i] = dglEdgeset_T_First(¤t[i]);
70
dglNode_T_Initialize(&nt, graph);
73
for (current_node = dglNode_T_First(&nt); current_node;
74
current_node = dglNode_T_Next(&nt)) {
75
dglInt32_t current_id = dglNodeGet_Id(graph, current_node);
77
if (tin[current_id] == 0) {
78
stack[0] = current_node;
80
parent[current_id] = 0;
82
dglInt32_t *node = stack[stack_size - 1];
83
dglInt32_t node_id = dglNodeGet_Id(graph, node);
85
if (tin[node_id] == 0) /*vertex visited for the first time */
86
min_tin[node_id] = tin[node_id] = ++time;
87
else { /*return from the recursion */
88
dglInt32_t to = dglNodeGet_Id(graph,
89
dglEdgeGet_Tail(graph,
92
if (min_tin[to] > tin[node_id]) { /*no path from the subtree above the current node */
93
Vect_list_append(bridge_list, dglEdgeGet_Id(graph, current_edge[node_id])); /*so it must be a bridge */
96
if (min_tin[to] < min_tin[node_id])
97
min_tin[node_id] = min_tin[to];
98
current_edge[node_id] = dglEdgeset_T_Next(¤t[node_id]); /*proceed to the next edge */
100
for (; current_edge[node_id]; current_edge[node_id] = dglEdgeset_T_Next(¤t[node_id])) { /*try next edges */
102
dglEdgeGet_Tail(graph, current_edge[node_id]);
104
dglEdgeGet_Id(graph, current_edge[node_id]);
105
if (abs(edge_id) == parent[node_id])
106
continue; /*skip edge we used to travel to this node */
107
int to_id = dglNodeGet_Id(graph, to);
109
if (tin[to_id]) { /*back edge, cannot be a bridge/articualtion point */
110
if (tin[to_id] < min_tin[node_id])
111
min_tin[node_id] = tin[to_id];
113
else { /*forward edge */
114
parent[to_id] = abs(edge_id);
115
stack[stack_size++] = to;
119
if (!current_edge[node_id])
120
stack_size--; /*current node completely processed */
125
dglNode_T_Release(&nt);
126
for (i = 1; i <= nnodes; i++)
127
dglEdgeset_T_Release(¤t[i]);
134
G_free(current_edge);