Advertisement

(SCC基于深度优先搜索DFS的强连通分量检索 C++实现) Coursera 斯坦福大学 算法课程 Programming Assignment #5

阅读量:

Divide and Conquer, Sorting and Searching, and Randomized Algorithms

  • 题目
  • 程序
  • 坑爹的地方

题目

第 1 个问题

Download the following text file:
SCC.txt

The file contains the edges of a directed graph. Vertices are labeled as positive integers from 1 to 875714. Every row indicates an edge, the vertex label in first column is the tail and the vertex label in second column is the head (recall the graph is directed, and the edges are directed from the first column vertex to the second column vertex). So for example, the 11th11^{th}11th row looks liks : “2 47646”. This just means that the vertex with label 2 has an outgoing edge to the vertex with label 47646

Your task is to code up the algorithm from the video lectures for computing strongly connected components (SCCs), and to run this algorithm on the given graph.

Output Format: You should output the sizes of the 5 largest SCCs in the given graph, in decreasing order of sizes, separated by commas (avoid any spaces). So if your algorithm computes the sizes of the five largest SCCs to be 500, 400, 300, 200 and 100, then your answer should be “500,400,300,200,100” (without the quotes). If your algorithm finds less than 5 SCCs, then write 0 for the remaining terms. Thus, if your algorithm computes only 3 SCCs whose sizes are 400, 300, and 100, then your answer should be “400,300,100,0,0” (without the quotes). (Note also that your answer should not have any spaces in it.)

WARNING: This is the most challenging programming assignment of the course. Because of the size of the graph you may have to manage memory carefully. The best way to do this depends on your programming language and environment, and we strongly suggest that you exchange tips for doing this on the discussion forums.

程序

复制代码
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    #include <regex>
    
    using namespace std;
    class vertex{
    private:
    public:
    int leader;
    bool visited;
    int vertexName;
    int finishTime;
    vector<int> edges;
    void push_back(int i){
        edges.push_back(i);
    }
    };
    
    vector<int> finishList;
    
    void readTxt(string file, vector<vertex>& fwdGraph, vector<vertex>& revGraph)
    {
    vector<int> temp_line;
    string line;
    ifstream in(file);
    regex pat_regex("[[:digit:]]+");
    int count = 0;
    while(getline(in, line)) {
        count++;
        for (sregex_iterator it(line.begin(), line.end(), pat_regex), end_it; it != end_it; ++it) {
            temp_line.push_back(stoi(it->str()));
        }
        fwdGraph[temp_line[0] - 1].push_back(temp_line[1] - 1);
        revGraph[temp_line[1] - 1].push_back(temp_line[0] - 1);
        temp_line.clear();
    }
    }
    
    int currentFinishTime = 0;
    int currentLeader = 0;
    
    void DFS(vector<vertex>& fwdGraph, vector<vertex>& revGraph, int i){
    revGraph[i].visited = true;
    revGraph[i].leader = currentLeader;
    for(int j = 0; j < revGraph[i].edges.size(); j++){
        if(revGraph[revGraph[i].edges[j]].visited == false){
            DFS(fwdGraph ,revGraph, revGraph[i].edges[j]);
        }
    }
    finishList[currentFinishTime] = i;
    
    currentFinishTime++;
    }
    
    void DFSLOOP(vector<vertex>& fwdGraph, vector<vertex>& revGraph){
    for(int i = revGraph.size() - 1; i >= 0; i--){
        if(revGraph[i].visited == false){
            currentLeader = i;
            DFS(fwdGraph, revGraph, i);
        }
    }
    }
    
    void DFS2(vector<vertex>& fwdGraph, int i){
    fwdGraph[i].visited = true;
    fwdGraph[i].leader = currentLeader;
    
    for(int j = 0; j < fwdGraph[i].edges.size(); j++){
        if(fwdGraph[fwdGraph[i].edges[j]].visited == false){
            DFS2(fwdGraph, fwdGraph[i].edges[j]);
        }
    }
    }
    
    void DFSLOOP2(vector<vertex>& fwdGraph){
    for(int j = finishList.size() - 1; j >= 0; j--){
        if(fwdGraph[finishList[j]].visited == false){
            currentLeader = finishList[j];
            DFS2(fwdGraph, finishList[j]);
        }
    }
    }
    
    void KosarajuTwoPass(vector<vertex>& fwdGraph, vector<vertex>& revGraph){
    currentFinishTime = 0;
    currentLeader = 0;
    DFSLOOP(fwdGraph, revGraph);
    
    currentFinishTime = 0;
    currentLeader = 0;
    DFSLOOP2(fwdGraph);
    }
    
    int main(){
    vector<vertex> fwdGraph;
    vector<vertex> revGraph;
    finishList.resize(875714);//875714
    fwdGraph.resize(875714);//875714
    revGraph.resize(875714);//875714
    readTxt("../num.txt", fwdGraph, revGraph);// Make sure the right path
    cout<<"finish read, fwd: "<<fwdGraph[0].edges.size()<<" rev: "<<revGraph[0].edges.size()<<endl;
    KosarajuTwoPass(fwdGraph, revGraph);
    
    vector<int> histogram;
    histogram.resize(875714);//875714
    
    for(int i = 0; i < fwdGraph.size(); i++){
        histogram[fwdGraph[i].leader]++;
    }
    
    vector<int> maxSCCnum;
    for(int i = 0; i < 5; i++){
        std::vector<int>::iterator biggest = std::max_element(std::begin(histogram), std::end(histogram));
        maxSCCnum.push_back(*biggest);
        cout<<*biggest<<",";
        histogram.erase(biggest);
    }
    
    cout<<"all Finish"<<endl;
    return 0;
    }
    //434821,968,459,313,211
    
    
    cpp
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-07-12/dgecOpkfqF8b6oN0aJmy3AXTQrit.png)

坑爹的地方

  1. 过多的递归容易爆栈,下次还是写循环吧。
  2. 写类的时候开始就应该考虑到调转边方向,换成更加合理的维护方式。
  3. 读数据的时候不要大量cout,否则刷屏时间太长会拖慢读取时间。
  4. 在调转的时候慎用O(n^2)的算法,很慢,几个小时。得写个indexList来查找。如果采用swap的话所有的边指向都会变,也不太好。
  5. 这个题目用链表实现可能会更好一些?

全部评论 (0)

还没有任何评论哟~