andres::graph
cut-vertices.hxx
1 #pragma once
2 #ifndef ANDRES_GRAPH_CUT_VERTICES_HXX
3 #define ANDRES_GRAPH_CUT_VERTICES_HXX
4 
5 #include <stack>
6 #include <vector>
7 #include "subgraph.hxx"
8 
9 namespace andres {
10 namespace graph {
11 
12 template<class GRAPH>
14 {
15  typedef GRAPH GraphType;
16 
18 
19  std::vector<std::size_t> depth_;
20  std::vector<std::size_t> min_successor_depth_;
21  std::vector<typename GraphType::VertexIterator> next_out_arc_;
22  std::vector<int> parent_;
23  std::vector<char> visited_;
24 };
25 
26 template<typename GRAPH, typename ARRAY>
27 inline void
29  const GRAPH&,
30  ARRAY&
31 );
32 
33 template<typename GRAPH, typename ARRAY>
34 inline void
36  const GRAPH&,
37  ARRAY&,
39 );
40 
41 template<typename GRAPH, typename SUBGRAPH, typename ARRAY>
42 inline void
44  const GRAPH&,
45  const SUBGRAPH&,
46  ARRAY&
47 );
48 
49 template<typename GRAPH, typename SUBGRAPH, typename ARRAY>
50 inline void
52  const GRAPH&,
53  const SUBGRAPH&,
54  ARRAY&,
56 );
57 
58 template<typename GRAPH, typename SUBGRAPH, typename ARRAY>
59 inline void
61  const GRAPH&,
62  const SUBGRAPH&,
63  std::size_t,
64  ARRAY&
65 );
66 
67 template<typename GRAPH, typename SUBGRAPH, typename ARRAY>
68 inline void
70  const GRAPH&,
71  const SUBGRAPH&,
72  std::size_t,
73  ARRAY&,
75 );
76 
77 template<typename GRAPH>
79  depth_(graph.numberOfVertices()),
80  min_successor_depth_(graph.numberOfVertices()),
81  next_out_arc_(graph.numberOfVertices()),
82  parent_(graph.numberOfVertices()),
83  visited_(graph.numberOfVertices())
84 {}
85 
96 template<typename GRAPH, typename ARRAY>
97 inline void
99  const GRAPH& graph,
100  ARRAY& is_cut_vertex
101 )
102 {
103  auto buffer = CutVerticesBuffers<GRAPH>(graph);
104  findCutVertices(graph, DefaultSubgraphMask<>(), is_cut_vertex, buffer);
105 }
106 
118 template<typename GRAPH, typename ARRAY>
119 inline void
121  const GRAPH& graph,
122  ARRAY& is_cut_vertex,
124 )
125 {
126  findCutVertices(graph, DefaultSubgraphMask<>(), is_cut_vertex, buffer);
127 }
128 
140 template<typename GRAPH, typename SUBGRAPH, typename ARRAY>
141 inline void
143  const GRAPH& graph,
144  const SUBGRAPH& subgraph_mask,
145  ARRAY& is_cut_vertex
146 )
147 {
148  auto buffer = CutVerticesBuffers<GRAPH>(graph);
149  findCutVertices(graph, subgraph_mask, is_cut_vertex, buffer);
150 }
151 
164 template<typename GRAPH, typename SUBGRAPH, typename ARRAY>
165 inline void
167  const GRAPH& graph,
168  const SUBGRAPH& subgraph_mask,
169  ARRAY& is_cut_vertex,
171 )
172 {
173  std::fill(buffer.parent_.begin(), buffer.parent_.end(), -2);
174 
175  for (std::size_t i = 0; i < graph.numberOfVertices(); ++i)
176  if (buffer.parent_[i] == -2 && subgraph_mask.vertex(i))
177  findCutVertices(graph, subgraph_mask, i, is_cut_vertex, buffer);
178 }
179 
192 template<typename GRAPH, typename SUBGRAPH, typename ARRAY>
193 inline void
195  const GRAPH& graph,
196  const SUBGRAPH& subgraph_mask,
197  std::size_t starting_vertex,
198  ARRAY& is_cut_vertex
199 )
200 {
201  auto buffer = CutVerticesBuffers<GRAPH>(graph);
202  findCutVertices(graph, subgraph_mask, starting_vertex, is_cut_vertex, buffer);
203 }
204 
218 template<typename GRAPH, typename SUBGRAPH, typename ARRAY>
219 inline void
221  const GRAPH& graph,
222  const SUBGRAPH& subgraph_mask,
223  std::size_t starting_vertex,
224  ARRAY& is_cut_vertex,
226 )
227 {
228  std::fill(buffer.visited_.begin(), buffer.visited_.end(), 0);
229 
230  std::stack<std::size_t> S;
231 
232  S.push(starting_vertex);
233  buffer.depth_[starting_vertex] = 0;
234  buffer.parent_[starting_vertex] = -1;
235 
236  while (!S.empty())
237  {
238  auto v = S.top();
239  S.pop();
240 
241  if (!buffer.visited_[v])
242  {
243  buffer.visited_[v] = 1;
244  is_cut_vertex[v] = 0;
245  buffer.next_out_arc_[v] = graph.verticesFromVertexBegin(v);
246  buffer.min_successor_depth_[v] = buffer.depth_[v];
247  }
248  else
249  {
250  auto to = *buffer.next_out_arc_[v];
251 
252  if (buffer.min_successor_depth_[to] >= buffer.depth_[v] && v != starting_vertex)
253  is_cut_vertex[v] = 1;
254 
255  buffer.min_successor_depth_[v] = std::min(buffer.min_successor_depth_[v], buffer.min_successor_depth_[to]);
256  ++buffer.next_out_arc_[v];
257  }
258 
259  while (buffer.next_out_arc_[v] != graph.verticesFromVertexEnd(v))
260  {
261  typename GRAPH::EdgeIterator e = graph.edgesFromVertexBegin(v) + (buffer.next_out_arc_[v] - graph.verticesFromVertexBegin(v));
262 
263  if (
264  !subgraph_mask.vertex(*buffer.next_out_arc_[v]) ||
265  !subgraph_mask.edge(*e)
266  )
267  {
268  ++buffer.next_out_arc_[v];
269  continue;
270  }
271 
272  auto to = *buffer.next_out_arc_[v];
273  if (buffer.visited_[to])
274  {
275  if(buffer.parent_[v] != to)
276  buffer.min_successor_depth_[v] = std::min(buffer.min_successor_depth_[v], buffer.depth_[to]);
277 
278  ++buffer.next_out_arc_[v];
279  }
280  else
281  {
282  S.push(v);
283  S.push(to);
284  buffer.parent_[to] = v;
285  buffer.depth_[to] = buffer.depth_[v] + 1;
286  break;
287  }
288  }
289  }
290 
291  std::size_t root_child_count = 0;
292  for (auto to = graph.verticesFromVertexBegin(starting_vertex); to != graph.verticesFromVertexEnd(starting_vertex); ++to)
293  if(buffer.parent_[*to] == starting_vertex)
294  ++root_child_count;
295 
296  if(root_child_count >= 2)
297  is_cut_vertex[starting_vertex] = 1;
298 }
299 
300 }
301 }
302 #endif