使用DFS来拆分强连通分量的算法实现

主要方法:

参考:https://www.cnblogs.com/LLGemini/p/4725952.html

一些数据类型的定义:

 

 Seperate strongly connected components in a directed graph with DFS:

  1 int MaxIndex(int* v, int size) {
  2     int max = v[0];
  3     int i = 0;
  4     for (auto it = 1; it < size; it++) {
  5         if (v[it] > max) {
  6             max = v[it];
  7             i = it;
  8         }
  9 
 10     }
 11     return i;
 12 }
 13 void Graph::StronglyConnectedComp(int nbNodes,int startFrom) {
 14     cout << "Detecting strongly connected components: " << endl;
 15     /*choose a vertex randomly or designate with parameter*/
 16     srand((unsigned int)time(NULL));
 17     Vertex* tempV;
 18     if (startFrom == -1) {
 19         int sze = listVertex.size();
 20         int rdm = rand() % sze;//[0,sze)
 21         tempV = listVertex[rdm];
 22     }
 23     else
 24         tempV = listVertex[startFrom - 1];
 25     int count = 0;// to check if all vertices have been visited
 26     int* mark = new int[nbNodes];// to store the numbers marked on vertex
 27     stack<Vertex* > myStack;// to assist dfs algo
 28     myStack.push(tempV);//initialization
 29     /*DFS algo to mark the vertices from leaves*/
 30     while (!myStack.empty()) {
 31         cout << "colored:" << myStack.top()->id << endl;
 32         myStack.top()->color = 1;// visit the vertex on top
 33         int visited = 0;// to check if all adjacent vertices have been visited
 34         
 35         for (auto it = myStack.top()->nextEdgeNode.begin(); it != myStack.top()->nextEdgeNode.end(); it++) {
 36             if (listVertex[it->first - 1]->color == 0)//O black(unvisited) & 1 white(visited))
 37             {
 38                 myStack.push(listVertex[it->first - 1]);
 39                 break;
 40             }
 41             else
 42                 visited++;
 43         }
 44         /*if the vertex and all its adjacent vertices have been visited, 
 45         which means the end of DFS, then mark it and pop it out*/
 46         if (visited == myStack.top()->nextEdgeNode.size() && myStack.top()->color == 1) {
 47             cout << "mark:" << myStack.top()->id<<endl;
 48             count++;
 49             mark[myStack.top()->id] = count;// mark the vertex
 50             myStack.pop();
 51         }
 52         /*check if all vertices in graph have been visited*/
 53         if (myStack.empty() && count < nbNodes) {
 54             for (auto it = listVertex.begin(); it != listVertex.end(); it++) {
 55                 if ((*it)->color == 0) {//O black(unvisited) & 1 white(visited)
 56                     myStack.push(*it);
 57                     break;
 58                 }    
 59             }
 60         }
 61     }
 62     /*end of DFS and the marking procedure*/
 63     /*restore the visit flag*/
 64     for (auto it = listVertex.begin(); it != listVertex.end(); it++) {
 65         (*it)->color = 0;//O black(unvisited) & 1 white(visited)
 66     }
 67 
 68     for (auto it = 0; it < nbNodes; it++)
 69         cout << "it:" << it << "number:" << mark[it] << endl;
 70     /*begin to reverse the edges with no change of original data*/
 71     vector<int>* tempAdjList = new vector<int>[nbNodes];//temporary assisting structure
 72     int max = MaxIndex(mark,nbNodes);
 73     cout << "maxindex:" << max << endl;
 74     for (auto it = listEdges.begin(); it != listEdges.end(); it++) {
 75         Vertex* temp;
 76         temp = (*it)->destination;
 77         (*it)->destination = (*it)->source;
 78         (*it)->source = temp;
 79         //store the just reversed data
 80         tempAdjList[(*it)->source->id].push_back((*it)->destination->id);
 81     }
 82     myStack.push(listVertex[max]);//initialization
 83     mark[max] = 0;
 84     int component = 0;
 85     int pushchecker = 1;
 86     while (!myStack.empty()) {
 87         if (myStack.top()->color == 0) {
 88             cout << "This is strongly connected component " << component+1 << "." << endl;
 89             myStack.top()->color = 1;//O black(unvisited) & 1 white(visited)
 90             mark[myStack.top()->id] = 0;//exclude visited vertex
 91             cout << "Vertex: " << myStack.top()->id + 1 << endl;
 92         }
 93         int popchecker = 0;
 94         for (auto it = tempAdjList[myStack.top()->id].begin(); it != tempAdjList[myStack.top()->id].end(); it++) {
 95             if (listVertex[*it]->color == 0) {//O black(unvisited) & 1 white(visited)
 96                 myStack.push(listVertex[*it]);
 97                 pushchecker++;
 98                 break;
 99             }
100             else
101                 popchecker++;
102         }
103         if (popchecker == tempAdjList[myStack.top()->id].size() && myStack.top()->color == 1)//O black(unvisited) & 1 white(visited)
104         {// end of the road, pop 
105             myStack.pop();
106         }
107         /*if the current component is all visited and not all vertices in graph are visited,
108         then add the vertex with the biggest number marked into stack*/
109         if (myStack.empty() && pushchecker < nbNodes) {
110             myStack.push(listVertex[MaxIndex(mark,nbNodes)]);
111             pushchecker++;
112             component++;
113         }
114     }
115 
116     delete[] mark;
117 }

测试数据1:

 

 结果:

 成功

测试数据2:

 

 结果:

 成功

原文地址:https://www.cnblogs.com/mrlonely2018/p/12057801.html