GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
bridge.c
Go to the documentation of this file.
1 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <grass/gis.h>
19 #include <grass/Vect.h>
20 #include <grass/glocale.h>
21 #include <grass/dgl/graph.h>
22 
34 int NetA_compute_bridges(dglGraph_s * graph, struct ilist *bridge_list)
35 {
36  int nnodes;
37  int bridges = 0;
38 
39  dglEdgesetTraverser_s *current; /*edge to be processed when the node is visited */
40  int *tin, *min_tin; /*time in, and smallest tin over all successors. 0 if not yet visited */
41  dglInt32_t *parent; /*edge from parent to the node */
42  dglInt32_t **stack; /*stack of nodes */
43  dglInt32_t **current_edge; /*current edge for each node */
45  dglInt32_t *current_node;
46  int stack_size;
47  int i, time;
48 
49  nnodes = dglGet_NodeCount(graph);
50  current =
51  (dglEdgesetTraverser_s *) G_calloc(nnodes + 1,
52  sizeof(dglEdgesetTraverser_s));
53  tin = (int *)G_calloc(nnodes + 1, sizeof(int));
54  min_tin = (int *)G_calloc(nnodes + 1, sizeof(int));
55  parent = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t));
56  stack = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *));
57  current_edge = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *));
58  if (!tin || !min_tin || !parent || !stack || !current) {
59  G_fatal_error(_("Out of memory"));
60  return -1;
61  }
62 
63  for (i = 1; i <= nnodes; i++) {
64  dglEdgeset_T_Initialize(&current[i], graph,
66  dglGetNode(graph, i)));
67  current_edge[i] = dglEdgeset_T_First(&current[i]);
68  tin[i] = 0;
69  }
70 
71  dglNode_T_Initialize(&nt, graph);
72 
73  time = 0;
74  for (current_node = dglNode_T_First(&nt); current_node;
75  current_node = dglNode_T_Next(&nt)) {
76  dglInt32_t current_id = dglNodeGet_Id(graph, current_node);
77 
78  if (tin[current_id] == 0) {
79  stack[0] = current_node;
80  stack_size = 1;
81  parent[current_id] = 0;
82  while (stack_size) {
83  dglInt32_t *node = stack[stack_size - 1];
84  dglInt32_t node_id = dglNodeGet_Id(graph, node);
85 
86  if (tin[node_id] == 0) /*vertex visited for the first time */
87  min_tin[node_id] = tin[node_id] = ++time;
88  else { /*return from the recursion */
89  dglInt32_t to = dglNodeGet_Id(graph,
90  dglEdgeGet_Tail(graph,
91  current_edge
92  [node_id]));
93  if (min_tin[to] > tin[node_id]) { /*no path from the subtree above the current node */
94  Vect_list_append(bridge_list, dglEdgeGet_Id(graph, current_edge[node_id])); /*so it must be a bridge */
95  bridges++;
96  }
97  if (min_tin[to] < min_tin[node_id])
98  min_tin[node_id] = min_tin[to];
99  current_edge[node_id] = dglEdgeset_T_Next(&current[node_id]); /*proceed to the next edge */
100  }
101  for (; current_edge[node_id]; current_edge[node_id] = dglEdgeset_T_Next(&current[node_id])) { /*try next edges */
102  dglInt32_t *to =
103  dglEdgeGet_Tail(graph, current_edge[node_id]);
104  dglInt32_t edge_id =
105  dglEdgeGet_Id(graph, current_edge[node_id]);
106  if (abs(edge_id) == parent[node_id])
107  continue; /*skip edge we used to travel to this node */
108  int to_id = dglNodeGet_Id(graph, to);
109 
110  if (tin[to_id]) { /*back edge, cannot be a bridge/articualtion point */
111  if (tin[to_id] < min_tin[node_id])
112  min_tin[node_id] = tin[to_id];
113  }
114  else { /*forward edge */
115  parent[to_id] = abs(edge_id);
116  stack[stack_size++] = to;
117  break;
118  }
119  }
120  if (!current_edge[node_id])
121  stack_size--; /*current node completely processed */
122  }
123  }
124  }
125 
126  dglNode_T_Release(&nt);
127  for (i = 1; i <= nnodes; i++)
128  dglEdgeset_T_Release(&current[i]);
129 
130  G_free(current);
131  G_free(tin);
132  G_free(min_tin);
133  G_free(parent);
134  G_free(stack);
135  G_free(current_edge);
136  return bridges;
137 }
dglInt32_t * dglEdgeGet_Tail(dglGraph_s *pGraph, dglInt32_t *pnEdge)
Definition: dglib/graph.c:494
dglInt32_t dglNodeGet_Id(dglGraph_s *pGraph, dglInt32_t *pnNode)
Definition: dglib/graph.c:213
void G_free(void *buf)
Free allocated memory.
Definition: gis/alloc.c:142
int dglEdgeset_T_Initialize(dglEdgesetTraverser_s *pT, dglGraph_s *pGraph, dglInt32_t *pnEdgeset)
Definition: dglib/graph.c:1499
int dglNode_T_Initialize(dglNodeTraverser_s *pT, dglGraph_s *pGraph)
Definition: dglib/graph.c:1356
void dglNode_T_Release(dglNodeTraverser_s *pT)
Definition: dglib/graph.c:1371
dglInt32_t dglEdgeGet_Id(dglGraph_s *pGraph, dglInt32_t *pnEdge)
Definition: dglib/graph.c:438
void dglEdgeset_T_Release(dglEdgesetTraverser_s *pT)
Definition: dglib/graph.c:1515
dglInt32_t * dglEdgeset_T_First(dglEdgesetTraverser_s *pT)
Definition: dglib/graph.c:1519
dglInt32_t * dglGetNode(dglGraph_s *pGraph, dglInt32_t nNodeId)
Definition: dglib/graph.c:155
int NetA_compute_bridges(dglGraph_s *graph, struct ilist *bridge_list)
Get number of bridges in the graph.
Definition: bridge.c:34
long dglInt32_t
Definition: type.h:37
int Vect_list_append(struct ilist *list, int val)
Append new item to the end of list if not yet present.
dglInt32_t * dglNode_T_First(dglNodeTraverser_s *pT)
Definition: dglib/graph.c:1387
dglInt32_t * dglNodeGet_OutEdgeset(dglGraph_s *pGraph, dglInt32_t *pnNode)
Definition: dglib/graph.c:170
int dglGet_NodeCount(dglGraph_s *pgraph)
Definition: dglib/graph.c:1241
int G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
dglInt32_t * dglNode_T_Next(dglNodeTraverser_s *pT)
Definition: dglib/graph.c:1402
dglInt32_t * dglEdgeset_T_Next(dglEdgesetTraverser_s *pT)
Definition: dglib/graph.c:1534