Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
biconnectivity.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file biconnectivity.cpp
1 /* This software is distributed under the GNU Lesser General Public License */
2 //==========================================================================
3 //
4 // biconnectivity.cpp
5 //
6 //==========================================================================
7 // $Id: biconnectivity.cpp,v 1.20 2002/02/28 15:40:52 raitner Exp $
8 
9 #include <GTL/biconnectivity.h>
10 
11 #ifdef __GTL_MSVCC
12 # ifdef _DEBUG
13 # ifndef SEARCH_MEMORY_LEAKS_ENABLED
14 # error SEARCH NOT ENABLED
15 # endif
16 # define new DEBUG_NEW
17 # undef THIS_FILE
18  static char THIS_FILE[] = __FILE__;
19 # endif // _DEBUG
20 #endif // __GTL_MSVCC
21 
23 
25 {
26  add_edges = false;
27  store_preds (true);
28  store_comp = false;
29  scan_whole_graph(true);
31 }
32 
34 {
35  dfs::reset ();
36 
37  if (store_comp) {
38  while (!node_stack.empty()) {
39  node_stack.pop();
40  }
41 
42  while (!edge_stack.empty()) {
43  edge_stack.pop();
44  }
45 
47  }
48 
49  if (add_edges) {
50  additional.erase (additional.begin(), additional.end());
51  }
52 
53  cut_points.erase (cut_points.begin(), cut_points.end());
55 }
56 
58 {
59  return G.is_undirected() && preds &&
60  dfs::check (G) == GTL_OK ? GTL_OK : GTL_ERROR;
61 }
62 
63 
64 //--------------------------------------------------------------------------
65 // Handler
66 //--------------------------------------------------------------------------
67 
68 
70 {
71  if (add_edges) {
72  dfs D;
73  D.scan_whole_graph (true);
74  D.check (G);
75  D.run (G);
76 
78  it = D.roots_begin();
79  end = D.roots_end();
80  start = *(*it);
81  ++it;
82 
83  for (; it != end; ++it) {
84  additional.push_back (G.new_edge (start, *(*it)));
85  }
86 
87  first_child.init (G, node());
88  }
89 
90  low_num.init (G);
91  in_component.init(G);
92  cut_count.init (G, 0);
93 
94  //
95  // Detect self loops and hide them.
96  //
97 
98  assert (self_loops.empty());
100  eend = G.edges_end();
101 
102  while (eit != eend) {
103  edge e = *eit;
104  eit++;
105  if (e.target() == e.source()) {
106  self_loops.push_back(e);
107  G.hide_edge(e);
108  }
109  }
110 }
111 
112 void biconnectivity::entry_handler (graph& G, node& curr, node& father)
113 {
114  if (add_edges) {
115  if (father != node()) {
116  if (first_child[father] == node()) {
117  first_child[father] = curr;
118  }
119  }
120  }
121 
122  low_num[curr] = dfs_number[curr];
123 }
124 
126 {
127  cut_count[st] = -1;
128 
129  //
130  // If this node has no adjacent edges, we
131  // must write down the component right here. This is because
132  // then the method after_recursive_call_handle is never
133  // executed.
134  //
135  // 28/2/2002 MR
136  //
137 
138  if (st.degree() == 0) {
140 
141  if (store_comp) {
142  component_iterator li = components.insert (
143  components.end(),
144  pair<list<node>,list<edge> > (list<node> (), list<edge> ()));
145 
146  (*li).first.push_back(st);
147  in_component[st] = li;
148  }
149  }
150 }
151 
153 {
154  if (store_comp) {
155  node_stack.push (n);
156  }
157 }
158 
159 
161 {
162  node curr = n.opposite (e);
163 
164  if (low_num[n] < low_num[curr]) {
165  low_num[curr] = low_num[n];
166  }
167 
168  if (low_num[n] >= dfs_num(curr)) {
169  //
170  // Component found
171  //
172 
173  if (store_comp) {
174  component_iterator li = components.insert (
175  components.end(),
176  pair<list<node>,list<edge> > (list<node> (), list<edge> ()));
177 
178  list<node>& component = (*li).first;
179  list<edge>& co_edges = (*li).second;
180 
181  //
182  // Nodes of biconnected component
183  //
184 
185  node tmp = node_stack.top();
186 
187  while (dfs_num(tmp) >= dfs_num (n)) {
188  node_stack.pop();
189  component.push_back (tmp);
190  in_component[tmp] = li;
191  if (node_stack.empty()) break;
192  else tmp = node_stack.top();
193  }
194 
195  component.push_back (curr);
196 
197  //
198  // edges of biconnected component
199  //
200 
201  edge ed = edge_stack.top();
202 
203  while ((dfs_num(ed.source()) >= dfs_num (n) &&
204  dfs_num(ed.target()) >= dfs_num (n)) ||
205  (dfs_num(ed.source()) == dfs_num (curr) &&
206  dfs_num(ed.target()) >= dfs_num (n)) ||
207  (dfs_num(ed.source()) >= dfs_num (n) &&
208  dfs_num(ed.target()) == dfs_num (curr))) {
209  edge_stack.pop();
210  co_edges.push_back (ed);
211  if (edge_stack.empty()) break;
212  else ed = edge_stack.top();
213  }
214  }
215 
216 
218 
219  //
220  // curr is cut point; increase counter
221  //
222 
223  ++cut_count[curr];
224 
225  if (add_edges) {
226  node father = (*preds)[curr];
227  node first = first_child[curr];
228 
229  if (father != node() && n == first) {
230  additional.push_back (G.new_edge (father, first));
231  }
232 
233  if (n != first) {
234  additional.push_back (G.new_edge (n, first));
235  }
236  }
237 
238  }
239 }
240 
242 {
243  node curr = n.opposite (e);
244 
245  //
246  // Store backedges at lower endpoint
247  //
248 
249  if (store_comp) {
250  if (dfs_num (curr) > dfs_num (n)) {
251  edge_stack.push (e);
252  }
253  }
254 
255  if (dfs_num (n) < low_num[curr]) {
256  low_num[curr] = dfs_number[n];
257  }
258 }
259 
261 {
262  if (cut_count[n] > 0) {
263  cut_points.push_back (n);
264  }
265 }
266 
268 {
269  list<edge>::iterator it = self_loops.begin();
270  list<edge>::iterator end = self_loops.end();
271 
272  while (it != end) {
273  G.restore_edge(*it);
274  if (store_comp) {
275  node adj = (*it).target();
276  component_iterator cit = in_component[adj];
277  (*cit).second.push_back(*it);
278  }
279 
280  it = self_loops.erase(it);
281  }
282 }
283 
285 
286 //--------------------------------------------------------------------------
287 // end of file
288 //--------------------------------------------------------------------------