123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- /*!
- \file lib/vector/neta/bridge.c
- \brief Network Analysis library - bridges
- Computes number of bridges in the graph.
- (C) 2009-2010 by Daniel Bundala, and the GRASS Development Team
- This program is free software under the GNU General Public License
- (>=v2). Read the file COPYING that comes with GRASS for details.
- \author Daniel Bundala (Google Summer of Code 2009)
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <grass/gis.h>
- #include <grass/vector.h>
- #include <grass/glocale.h>
- #include <grass/dgl/graph.h>
- /*!
- \brief Get number of bridges in the graph.
- Bridge is an array containing the indices of the bridges.
- \param graph input graph
- \param[out] bridge_list list of bridges
- \return number of bridges, -1 on error
- */
- int NetA_compute_bridges(dglGraph_s * graph, struct ilist *bridge_list)
- {
- int nnodes;
- int bridges = 0;
- dglEdgesetTraverser_s *current; /*edge to be processed when the node is visited */
- int *tin, *min_tin; /*time in, and smallest tin over all successors. 0 if not yet visited */
- dglInt32_t *parent; /*edge from parent to the node */
- dglInt32_t **stack; /*stack of nodes */
- dglInt32_t **current_edge; /*current edge for each node */
- dglNodeTraverser_s nt;
- dglInt32_t *current_node;
- int stack_size;
- int i, time;
- nnodes = dglGet_NodeCount(graph);
- current =
- (dglEdgesetTraverser_s *) G_calloc(nnodes + 1,
- sizeof(dglEdgesetTraverser_s));
- tin = (int *)G_calloc(nnodes + 1, sizeof(int));
- min_tin = (int *)G_calloc(nnodes + 1, sizeof(int));
- parent = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t));
- stack = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *));
- current_edge = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *));
- if (!tin || !min_tin || !parent || !stack || !current) {
- G_fatal_error(_("Out of memory"));
- return -1;
- }
- for (i = 1; i <= nnodes; i++) {
- dglEdgeset_T_Initialize(¤t[i], graph,
- dglNodeGet_OutEdgeset(graph,
- dglGetNode(graph, i)));
- current_edge[i] = dglEdgeset_T_First(¤t[i]);
- tin[i] = 0;
- }
- dglNode_T_Initialize(&nt, graph);
- time = 0;
- for (current_node = dglNode_T_First(&nt); current_node;
- current_node = dglNode_T_Next(&nt)) {
- dglInt32_t current_id = dglNodeGet_Id(graph, current_node);
- if (tin[current_id] == 0) {
- stack[0] = current_node;
- stack_size = 1;
- parent[current_id] = 0;
- while (stack_size) {
- dglInt32_t *node = stack[stack_size - 1];
- dglInt32_t node_id = dglNodeGet_Id(graph, node);
- if (tin[node_id] == 0) /*vertex visited for the first time */
- min_tin[node_id] = tin[node_id] = ++time;
- else { /*return from the recursion */
- dglInt32_t to = dglNodeGet_Id(graph,
- dglEdgeGet_Tail(graph,
- current_edge
- [node_id]));
- if (min_tin[to] > tin[node_id]) { /*no path from the subtree above the current node */
- Vect_list_append(bridge_list, dglEdgeGet_Id(graph, current_edge[node_id])); /*so it must be a bridge */
- bridges++;
- }
- if (min_tin[to] < min_tin[node_id])
- min_tin[node_id] = min_tin[to];
- current_edge[node_id] = dglEdgeset_T_Next(¤t[node_id]); /*proceed to the next edge */
- }
- for (; current_edge[node_id]; current_edge[node_id] = dglEdgeset_T_Next(¤t[node_id])) { /*try next edges */
- dglInt32_t *to =
- dglEdgeGet_Tail(graph, current_edge[node_id]);
- dglInt32_t edge_id =
- dglEdgeGet_Id(graph, current_edge[node_id]);
- if (labs(edge_id) == parent[node_id])
- continue; /*skip edge we used to travel to this node */
- int to_id = dglNodeGet_Id(graph, to);
- if (tin[to_id]) { /*back edge, cannot be a bridge/articualtion point */
- if (tin[to_id] < min_tin[node_id])
- min_tin[node_id] = tin[to_id];
- }
- else { /*forward edge */
- parent[to_id] = labs(edge_id);
- stack[stack_size++] = to;
- break;
- }
- }
- if (!current_edge[node_id])
- stack_size--; /*current node completely processed */
- }
- }
- }
- dglNode_T_Release(&nt);
- for (i = 1; i <= nnodes; i++)
- dglEdgeset_T_Release(¤t[i]);
- G_free(current);
- G_free(tin);
- G_free(min_tin);
- G_free(parent);
- G_free(stack);
- G_free(current_edge);
- return bridges;
- }
|