GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
articulation_point.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 
33  struct ilist *articulation_list)
34 {
35  int nnodes;
36  int points = 0;
37 
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; /*parents of the nodes */
41  dglInt32_t **stack; /*stack of nodes */
42  dglInt32_t **current_edge; /*current edge for each node */
43  int *mark; /*marked articulation points */
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  mark = (int *)G_calloc(nnodes + 1, sizeof(int));
59  if (!tin || !min_tin || !parent || !stack || !current || !mark) {
60  G_fatal_error(_("Out of memory"));
61  return -1;
62  }
63 
64  for (i = 1; i <= nnodes; i++) {
65  dglEdgeset_T_Initialize(&current[i], graph,
67  dglGetNode(graph, i)));
68  current_edge[i] = dglEdgeset_T_First(&current[i]);
69  tin[i] = mark[i] = 0;
70  }
71 
72  dglNode_T_Initialize(&nt, graph);
73 
74  time = 0;
75  for (current_node = dglNode_T_First(&nt); current_node;
76  current_node = dglNode_T_Next(&nt)) {
77  dglInt32_t current_id = dglNodeGet_Id(graph, current_node);
78 
79  if (tin[current_id] == 0) {
80  int children = 0; /*number of subtrees rooted at the root/current_node */
81 
82  stack[0] = current_node;
83  stack_size = 1;
84  parent[current_id] = NULL;
85  while (stack_size) {
86  dglInt32_t *node = stack[stack_size - 1];
87  dglInt32_t node_id = dglNodeGet_Id(graph, node);
88 
89  if (tin[node_id] == 0) /*vertex visited for the first time */
90  min_tin[node_id] = tin[node_id] = ++time;
91  else { /*return from the recursion */
92  dglInt32_t to = dglNodeGet_Id(graph,
93  dglEdgeGet_Tail(graph,
94  current_edge
95  [node_id]));
96  if (min_tin[to] >= tin[node_id]) /*no path from the subtree above the current node */
97  mark[node_id] = 1; /*so the current node must be an articulation point */
98 
99  if (min_tin[to] < min_tin[node_id])
100  min_tin[node_id] = min_tin[to];
101  current_edge[node_id] = dglEdgeset_T_Next(&current[node_id]); /*proceed to the next edge */
102  }
103  for (; current_edge[node_id]; current_edge[node_id] = dglEdgeset_T_Next(&current[node_id])) { /* try next edges */
104  dglInt32_t *to =
105  dglEdgeGet_Tail(graph, current_edge[node_id]);
106  if (to == parent[node_id])
107  continue; /*skip parrent */
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  if (node_id == current_id)
116  children++; /*if root, increase number of children */
117  parent[to_id] = node;
118  stack[stack_size++] = to;
119  break;
120  }
121  }
122  if (!current_edge[node_id])
123  stack_size--; /*current node completely processed */
124  }
125  if (children > 1)
126  mark[current_id] = 1; /*if the root has more than 1 subtrees rooted at it, then it is an
127  * articulation point */
128  }
129  }
130 
131  for (i = 1; i <= nnodes; i++)
132  if (mark[i]) {
133  points++;
134  Vect_list_append(articulation_list, i);
135  }
136 
137  dglNode_T_Release(&nt);
138  for (i = 1; i <= nnodes; i++)
139  dglEdgeset_T_Release(&current[i]);
140 
141  G_free(current);
142  G_free(tin);
143  G_free(min_tin);
144  G_free(parent);
145  G_free(stack);
146  G_free(current_edge);
147  return points;
148 }
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
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
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
return NULL
Definition: dbfopen.c:1394
int dglGet_NodeCount(dglGraph_s *pgraph)
Definition: dglib/graph.c:1241
int NetA_articulation_points(dglGraph_s *graph, struct ilist *articulation_list)
Get number of articulation points in the graph.
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