void RecurrentNN::strongConnect(long v, long index, std::vector<long> &stack, std::vector<RecurrentNN::CycleNode> &nodes, std::vector<std::vector<long> > &components) { std::vector<long> connectedComponent; CycleNode &cn = nodes[v]; cn.index = index; cn.lowlink = index; index = index+1; stack.push_back(v); std::vector<DelayEdge> succesors = outputsFromNode(v); for (long i=0; i<succesors.size(); i++) { long toNode = succesors[i].nodeTo; CycleNode &nextN = nodes[toNode]; if (nextN.index < 0) { strongConnect(toNode, index, stack, nodes, components); cn.lowlink = std::min(nextN.lowlink, cn.lowlink); } else if (std::find(stack.begin(), stack.end(), toNode) != stack.end()) { // Successor w is in stack S and hence in the current SCC cn.lowlink = std::min(nextN.index, cn.lowlink); } } if (cn.lowlink == cn.index) { long nodeFrom = v; long nodeTo = -1; do { nodeTo = stack.back(); stack.pop_back(); connectedComponent.push_back(nodeTo); } while (nodeFrom != nodeTo); components.push_back(connectedComponent); } }
void SCCDetector::strongConnect(uint v) { // Set the depth index for v to the smallest unused index m_indexes[v] = m_index; m_lowlinks[v] = m_index; m_index++; m_stack.push(v); m_in_stack[v] = true; // Consider successors of v for (uint edgeInd = 0; edgeInd < m_graph->conn_vec.size(); ++edgeInd) { // for each (v, w) in E cola::Edge edge = m_graph->edges[edgeInd]; if ( (edge.first == v) && m_graph->conn_vec[edgeInd]->isDirected() && m_graph->conn_vec[edgeInd]->obeysDirectedEdgeConstraints() ) { int w = edge.second; if (m_indexes[w] == k_undefined) { // Successor w has not yet been visited; recurse on it strongConnect(w); m_lowlinks[v] = qMin(m_lowlinks[v], m_lowlinks[w]); } else if (m_in_stack[w]) { // Successor w is in stack S and hence in the current SCC m_lowlinks[v] = qMin(m_lowlinks[v], m_indexes[w]); } } } // If v is a root node, pop the stack and generate an SCC if (m_lowlinks[v] == m_indexes[v]) { // start a new strongly connected component m_scc_index++; uint w; do { w = m_stack.pop(); m_in_stack[w] = false; // add w to current strongly connected component m_scc_indexes[w] = m_scc_index; } while (w != v); } }
int main() { int N, P; // number of persons number of shares link int scanRes = 0; //read N and read P; scanRes = scanf("%d %d", &N, &P); if(scanRes <= 0 && scanRes != EOF) { std::cout << "Error reading from standard input." << std::endl; } //initialize the shared vector equal to number of person for(int i = 0; i < N+1 ; i++) { nodes.push_back(new Node()); } adjacencias = std::vector<std::vector<int> > (N+1); //for each share, read for(int i = 0 ; i < P ; i++) { int u, v; scanRes = scanf("%d %d", &u, &v); if(scanRes <= 0 && scanRes != EOF) { std::cout << "Error reading from standard input." << std::endl; } adjacencias[u].push_back(v); } for(unsigned long u = 1; u != nodes.size(); u++) { if (nodes[u]->getIndex() == UNDEFINED){ strongConnect(u); } } #ifdef DEBUG std::cout << "--- Scc associado ---" << std::endl; for(unsigned long u = 1; u != nodes.size(); u++) { std::cout << u << ": " << nodes[u]->getScc() << std::endl; } #endif printf("%d\n", numberOfSCC); printf("%d\n", sccMaxSize); printf("%d\n", numberOfIsolatedSCC + numberOfSCC); return 0; }
ClusteringResult TarjansAlgorithm::run(const Eigen::MatrixXd & adjacencies_) { adjacencies = &adjacencies_; n = adjacencies->rows(); if (n != adjacencies->cols()) { throw std::runtime_error("Adjacency matrix must be quadratic!"); } index = 0; nodes.clear(); for (unsigned i = 0; i < n; i++) { nodes.emplace_back(); nodes.back().adjacencyIdx = i; } stack = std::stack<Node*>(); ClusteringResult res; res.labels.resize(n); for (auto & node : nodes) { if (node.index == -1) { std::vector<unsigned> componentIndexes = strongConnect(node); if (componentIndexes.size() > 0) { for (unsigned idx : componentIndexes) { res.labels[idx] = res.numClusters; } res.numClusters++; } } } return res; }
std::vector<unsigned> TarjansAlgorithm::strongConnect(Node & v) { v.index = index; v.lowLink = index; index++; stack.push(&v); v.onStack = true; // consider successors of v for (unsigned e = 0; e < n; e++) { if ((*adjacencies)(v.adjacencyIdx, e) > 0) // edge { Node & w = nodes[e]; if (w.index == -1) { strongConnect(w); v.lowLink = std::min(v.lowLink, w.lowLink); } else if (w.onStack) { v.lowLink = std::min(v.lowLink, w.index); } } } // If v is a root node, pop the stack and generate a strongly connected component std::vector<unsigned> componentIndexes; if (v.lowLink == v.index) { Node * w; do { w = stack.top(); stack.pop(); w->onStack = false; componentIndexes.push_back(w->adjacencyIdx); } while (w != &v); } return componentIndexes; }
QVector<int> SCCDetector::stronglyConnectedComponentIndexes(GraphData *graph) { m_graph = graph; m_index = 0; m_scc_index = 0; int shapesCount = m_graph->shape_vec.size(); m_indexes = QVector<int>(shapesCount, k_undefined); m_scc_indexes = QVector<int>(shapesCount, 0); m_lowlinks = QVector<int>(shapesCount, 0); m_in_stack = QVector<bool>(shapesCount, false); m_stack.clear(); for (int i = 0; i < shapesCount; ++i) { if (m_indexes[i] == k_undefined) { strongConnect(i); } } return m_scc_indexes; }
//http://en.wikipedia.org/wiki/Tarjan’s_strongly_connected_components_algorithm std::vector<std::vector<long> > RecurrentNN::cycleSort() { std::vector<std::vector<long> > sorted; std::vector<long> stack; std::vector<RecurrentNN::CycleNode> cycleNodes; long index = 0; // make a CycleNode for each actual node for (long i=0; i<nodes.size(); i++) { CycleNode cn = CycleNode(i); cycleNodes.push_back(cn); } for (long i=0; i<cycleNodes.size(); i++) { if (cycleNodes[i].index < 0) { strongConnect(i, index, stack, cycleNodes, sorted); } } return sorted; }
void strongConnect(int u) { Node* raiz = nodes[u]; raiz->setup(); nodeStack.push(u); raiz->setInStack(true); for(unsigned long v = 0; v < adjacencias[u].size(); v++) { int vizinho = adjacencias[u][v]; Node* noVizinho = nodes[vizinho]; if(noVizinho->getIndex() == UNDEFINED){ strongConnect(vizinho); raiz->setLowIndex(std::min(raiz->getLowIndex(), noVizinho->getLowIndex())); } else if (noVizinho->isInStack()){ raiz->setLowIndex(std::min(raiz->getLowIndex(), noVizinho->getIndex())); } } if(raiz->getLowIndex() == raiz->getIndex() ){ numberOfSCC++; int currentSCCSize = 0; int poppedNodeIndex = 0; Node* node = NULL; bool run_once = false; #ifdef DEBUG std::cout << "--- popping ---" << std::endl; #endif do { poppedNodeIndex = nodeStack.top(); #ifdef DEBUG std::cout << "popped: " << poppedNodeIndex << std::endl; #endif nodeStack.pop(); nodes[poppedNodeIndex]->setInStack(false); node = nodes[poppedNodeIndex]; currentSCCSize++; node->setScc(numberOfSCC); if(!run_once && find(poppedNodeIndex, last_rootNode_popped)){ #ifdef DEBUG std::cout << "!! found: " << poppedNodeIndex << " " << last_rootNode_popped << std::endl; #endif numberOfIsolatedSCC--; run_once = true; } } while(raiz->getIndex() != node->getIndex()); last_rootNode_popped = poppedNodeIndex; run_once = false; node->setScc(numberOfSCC); sccMaxSize = std::max(sccMaxSize, currentSCCSize); } }