#include "biconnected.h" #include "../../classes/graph.h" #include "../../common/utils.h" node_t index_edge(std::vector>& edges, const std::pair& target) { for (int i = edges.size() - 1;i >= 0;i--) { if ((edges[i].first == target.first) && (edges[i].second == target.second)) { return i; } } return -1; } py::object _biconnected_dfs_record_edges(py::object G, py::object need_components) { py::list ret = py::list(); std::unordered_set visited; Graph& G_ = G.cast(); node_dict_factory &nodes_list = G_.node; for (node_dict_factory::iterator iter = nodes_list.begin();iter != nodes_list.end();iter++) { node_t start_id = iter->first; if (visited.find(start_id) != visited.end()) { continue; } std::unordered_map discovery; std::unordered_map low; node_t root_children = 0; discovery.emplace(start_id, 0); low.emplace(start_id, 0); visited.emplace(start_id); std::vector> edge_stack; std::vector stack; adj_attr_dict_factory& start_adj = G_.adj[start_id]; NeighborIterator neighbors_iter = NeighborIterator(start_adj); stack_node initial_stack_node(start_id, start_id, neighbors_iter); stack.emplace_back(initial_stack_node); while (!stack.empty()) { stack_node& node_info = stack.back(); node_t node_grandparent_id = node_info.grandparent; node_t node_parent_id = node_info.parent; try { node_t node_child_id = node_info.neighbors_iter.next(); if (node_grandparent_id == node_child_id) { continue; } if (visited.find(node_child_id) != visited.end()) { if (discovery[node_child_id] <= discovery[node_parent_id]) { low[node_parent_id] = std::min(low[node_parent_id], discovery[node_child_id]); if (need_components.cast()) { edge_stack.emplace_back(std::make_pair(node_parent_id, node_child_id)); } } } else { low[node_child_id] = discovery[node_child_id] = discovery.size(); visited.emplace(node_child_id); adj_attr_dict_factory& node_child_adj = G_.adj[node_child_id]; NeighborIterator child_neighbors_iter = NeighborIterator(G_.adj[node_child_id]); stack.emplace_back(node_parent_id, node_child_id, child_neighbors_iter); if (need_components.cast()) { edge_stack.emplace_back(std::make_pair(node_parent_id, node_child_id)); } } } catch (int) { stack.pop_back(); if (stack.size() > 1) { if (low[node_parent_id] >= discovery[node_grandparent_id]) { if (need_components.cast()) { py::list tmp_ret = py::list(); std::pair iter_edge = std::make_pair(-1, -1); while ((iter_edge.first != node_grandparent_id || iter_edge.second != node_parent_id)) { iter_edge = edge_stack.back(); edge_stack.pop_back(); tmp_ret.append(py::make_tuple(G_.id_to_node[py::cast(iter_edge.first)], G_.id_to_node[py::cast(iter_edge.second)])); } ret.append(tmp_ret); } else { ret.append(G_.id_to_node[py::cast(node_grandparent_id)]); } } low[node_grandparent_id] = std::min(low[node_grandparent_id], low[node_parent_id]); } else if (stack.size() > 0) { root_children += 1; if (need_components.cast()) { std::pair target = std::make_pair(node_grandparent_id, node_parent_id); node_t ind = index_edge(edge_stack, target); if (ind != -1) { py::list tmp_ret = py::list(); for (node_t z = ind;z < edge_stack.size();z++) { tmp_ret.append(py::make_tuple(G_.id_to_node[py::cast(edge_stack[z].first)], G_.id_to_node[py::cast(edge_stack[z].second)])); } ret.append(tmp_ret); } } } } } if (!need_components.cast()) { if (root_children > 1) { ret.append(G_.id_to_node(start_id)); } } } return ret; }