bridge.c 4.2 KB

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