用C++实现以下功能

(1)输入一个无向图,打印出它的所有连通分量。如
下示例,
连通分量有2个,分别为{1,2,4,5}, {3,6}
(2)输入一个有向图,打印出它的所有强连通分量。
如下示例,
强连通分量有3个,分别为{1}, {4}, {2,5,3,6}

img

输入图的格式是什么?

第二题:打印出有向图的所有强连通分量。

#include<iostream>
#include<stack>
#include<vector>
using namespace std;
int n,m,cnt,cntb;
vector<int> edge[101];
vector<int> belong[101];
bool instack[101];
int dfn[101];
int low[101];//LOW[]作为每个点在这颗树中的,最小的子树的根,每次保证最小,like它的父亲结点的时间戳这种感觉。如果它自己的LOW[]最小,那这个点就应该从新分配,变成这个强连通分量子树的根节点。
stack<int> s;
void Tarjan(int u) //tarjan算法
{
    ++cnt;
    dfn[u]=low[u]=cnt;//DFN[]作为这个点搜索的次序编号(时间戳),简单来说就是 第几个被搜索到的
    s.push(u);
    instack[u]=true;
    for(int i=0;i<edge[u].size();++i)
    {
        int v=edge[u][i];
        if(!dfn[v])//如果节点v未被访问过
        {
            Tarjan(v);// 继续向下找
            low[u]=min(low[u],low[v]);
        }
        else if(instack[v])
            low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u])//如果节点u是强连通分量的根
    {
        ++cntb;
        int node;
        do
        {
            node=s.top();
            s.pop();
            instack[node]=false;
            belong[cntb].push_back(node);
        }while(node!=u);
    }
}
int main()
{
    cout<<"求有向图强连通分量:\n";
    cout<<"请输入节点的个数n:";

    cin>>n;
    cout<<"请输入边的条数m:";
    cin>>m;

    cout<<"请输入"<<m<<"条边:\n";
    for(int i=1;i<=m;++i)
    {
        int u,v;
        cin>>u>>v;
        edge[u].push_back(v);//输入边
    }
    Tarjan(1);
    for(int i=1;i<=cntb;++i)
    {
        cout<<"连通分量"<<i<<" : ";
        for(int j=0;j<belong[i].size();++j)
            cout<<belong[i][j]<<" ";
        cout<<endl;
    }
    return 0;
}


img

无向图能求了, 有向图还有问题。。。

img

好的


#include <iostream>
#include <vector>
#include <cassert>
using namespace std;

// 稀疏图 - 邻接表
class SparseGraph{

private:
    int n, m;       // 节点数和边数
    bool directed;  // 是否为有向图
    vector<vector<int> > g;  // 图的具体数据

public:
    // 构造函数
    SparseGraph( int n , bool directed ){
        assert( n >= 0 );
        this->n = n;
        this->m = 0;    // 初始化没有任何边
        this->directed = directed;
        // g初始化为n个空的vector, 表示每一个g[i]都为空, 即没有任和边
        g = vector<vector<int> >(n, vector<int>());
    }

    ~SparseGraph(){ }

    int V(){ return n;} // 返回节点个数
    int E(){ return m;} // 返回边的个数

    // 向图中添加一个边
    void addEdge( int v, int w ){

        assert( v >= 0 && v < n );
        assert( w > 0 && w < n );

        g[v].push_back(w);
        if( v != w && !directed )
            g[w].push_back(v);
            
        m ++;
    }

    // 验证图中是否有从v到w的边
    bool hasEdge( int v , int w ){

        assert( v >= 0 && v < n );
        assert( w >= 0 && w < n );

        for( int i = 0 ; i < g[v].size() ; i ++ )
            if( g[v][i] == w )
                return true;
        return false;
    }

    // 显示图的信息
    void show(){

        for( int i = 0 ; i < n ; i ++ ){
            cout<<"vertex "<<i<<":\t";
            for( int j = 0 ; j < g[i].size() ; j ++ )
                cout<<g[i][j]<<"\t";
            cout<<endl;
        }
    }

    // 邻边迭代器, 传入一个图和一个顶点,
    // 迭代在这个图中和这个顶点向连的所有顶点
    class adjIterator{
    private:
        SparseGraph &G; // 图G的引用
        int v;
        int index;

    public:
        // 构造函数
        adjIterator(SparseGraph &graph, int v): G(graph){
            this->v = v;
            this->index = 0;
        }

        ~adjIterator(){}

        // 返回图G中与顶点v相连接的第一个顶点
        int begin(){
            index = 0;
            if( G.g[v].size() )
                return G.g[v][index];
            // 若没有顶点和v相连接, 则返回-1
            return -1;
        }

        // 返回图G中与顶点v相连接的下一个顶点
        int next(){
            index ++;
            if( index < G.g[v].size() )
                return G.g[v][index];
            // 若没有顶点和v相连接, 则返回-1
            return -1;
        }

        // 查看是否已经迭代完了图G中与顶点v相连接的所有顶点
        bool end(){
            return index >= G.g[v].size();
        }
    };
};


// 求无权图的联通分量
template <typename Graph>
class Component{

private:
    Graph &G;       // 图的引用
    bool *visited;  // 记录dfs的过程中节点是否被访问
    int ccount;     // 记录联通分量个数
    int *id;        // 每个节点所对应的联通分量标记

    // 图的深度优先遍历
    void dfs( int v ){
        visited[v] = true;
        id[v] = ccount;
        typename Graph::adjIterator adj(G, v);
        for( int i = adj.begin() ; !adj.end() ; i = adj.next() ){
            if( !visited[i] )
                dfs(i);
        }
    }

public:
    // 构造函数, 求出无权图的联通分量
    Component(Graph &graph): G(graph){

        // 算法初始化
        visited = new bool[G.V()];
        id = new int[G.V()];
        ccount = 0;
        for( int i = 0 ; i < G.V() ; i ++ ){
            visited[i] = false;
            id[i] = -1;
        }

        // 求图的联通分量
        for( int i = 0 ; i < G.V() ; i ++ )
            if( !visited[i] ){
                dfs(i);
                ccount ++;
            }
    }

    // 析构函数
    ~Component(){
        delete[] visited;
        delete[] id;
    }

    // 返回图的联通分量个数
    void showComponents(){
        vector<vector<int> > components;
        components = vector<vector<int> > (G.V(), vector<int>(0)); 
        
        for(int i = 1; i < G.V(); i++)
            if(id[i] != -1)
                components[id[i]].push_back(i);
        
        cout << endl;
        cout << "联通分量分别是:" << endl; 
        for(int i = 1; i < components.size(); i++){
            for(int j = 0; j < components[i].size(); j++)
                cout << components[i][j] << " ";
            if (components[i].size() != 0)
                cout << endl;
        }

    }

    // 查询点v和点w是否联通
    bool isConnected( int v , int w ){
        assert( v >= 0 && v < G.V() );
        assert( w >= 0 && w < G.V() );
        return id[v] == id[w];
    }
};



void calculateComponents(){
    int direct;
    int V, E;  // 记录定点数和边数 
    
    cout << "请选择:" << endl;
    cout << "0. 无向图" << endl;
    cout << "1. 有向图" << endl;
    cin >> direct;
    
    cout << "请输入顶点数, 边数:" << endl;
    cin >> V >> E;
    cout << "请输入 " << E << " 条边" << endl;
    
    SparseGraph gragh = SparseGraph(V + 1, bool(direct));
    int node1, node2;      // 记录顶点 , 编号从1开始 
    for (int i = 0; i < E; i++){  // 构造图 
        cin >> node1 >> node2;
        gragh.addEdge(node1, node2);
    }
    
    Component<SparseGraph> component(gragh);
    component.showComponents();
}

int main(){
    calculateComponents();
}