無向グラフの接続性、有向グラフの強力な接続性、リング

無向グラフが接続されているかどうかを確認します

  1. DFS、BFSは、すべての頂点にアクセスできるかどうかに関係なく、グラフを走査します。
  2. そして、セットを確認してください。

グラフにリングがあるかどうかを確認します

有向グラフ:有向グラフのリングは、特に同じ方向のリングを指します

[外部リンク画像の転送に失敗しました。ソースサイトにヒル防止リンクメカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img-hsVSlpDr-1584972787667)(http://note.youdao.com/noteshare? id = d98bba32026574ec204adac734ccdaf7&sub = 4699EAF86DEF463A8BE50FC418E4108A)]
1。トポロジカルソート

//邻接表版
class Solution{
    
    
public:
    bool topologicalSort(vector<vector<int> >& graph){
    
    
        int V = graph.size();
        int in_degree[V] = {
    
    };
        for(vector<int> v:graph){
    
    
            for(int x:v) in_degree[x]++;
        }
        //topo
        int num = 0; //拓扑排序成功的顶点个数
        queue<int> q;
        for(int i=0; i<V; i++){
    
    
            if(in_degree[i]==0) q.push(i);
        }
        while(!q.empty()){
    
    
            int v = q.front();
            q.pop();
            cout<<v<<' ';
            num++;
            for(int u:graph[v]){
    
    
                in_degree[u]--;
                if(in_degree[u]==0) q.push(u);
            }
        }
        if(num==V) return true;
        else return false;
    }
};

2.有向グラフのタージャンアルゴリズム(基本的にDFS)
の強連結成分は、リングまたはポイントのいずれかです。タージャン

//邻接矩阵版
class Solution{
    
    
public:
    int V, time; //顶点个数,时间戳
    vector<int> dfn, low;
    vector<bool> in_stack; //记录顶点是否在栈内
    stack<int> s;

    vector<vector<int> > tarjan(vector<vector<int> >& graph){
    
    
        //init
        V = graph.size();
        dfn.resize(V, 0); //dfn[i]=0还可表示i还未访问到
        low.resize(V, 0);
        in_stack.resize(V, false);
        time = 1;
        vector<vector<int> > ans;
        //tarjan
        for(int i=0; i<V; i++){
    
    
            if(dfn[i]==0) DFS(i, graph, ans);
        }
        return ans;
    }

    void DFS(int i, vector<vector<int> >& graph, vector<vector<int> >& ans){
    
    
        s.push(i);
        in_stack[i] = true;
        dfn[i] = low[i] = time++;
        for(int j; j<V; j++){
    
    
            if(graph[i][j]){
    
    
                if(dfn[j]==0){
    
    
                    DFS(j, graph, ans);
                    low[i] = min(low[i], low[j]);
                }
                else if(in_stack[j]) low[i] = min(low[i], dfn[j]);
            }
        }
        if(dfn[i]==low[i]){
    
    
            vector<int> temp;
            int x;
            do{
    
    
                x = s.top();
                s.pop();
                temp.emplace_back(x);
            }while(x!=i);
            ans.emplace_back(temp);
        }
        return;
    }
};

無向グラフ

1.Nアルゴリズム

//邻接矩阵版
class Solution{
    
    
public:
    bool nAlgorithm(vector<vector<int> >& graph){
    
    
        int V = graph.size();
        int degree[V] = {
    
    };
        for(int i=0; i<V; i++){
    
    
            for(int j=0; j<V; j++){
    
    
                if(graph[i][j]!=0){
    
    
                    degree[i]++;
                    degree[j]++;
                }
            }
        }
        //把所有度<=1的顶点入队,只要入过队,就一定不在环里
        queue<int> q;
        int num = 0; //入过队的顶点数
        for(int i=0; i<V; i++){
    
    
            if(degree[i]<=1) q.push(i);
        }
        while(!q.empty()){
    
    
            int v = q.front();
            q.pop();
            num++;
            for(int j=0; j<V; j++){
    
    
                if(graph[v][j]!=0){
    
    
                    degree[v]--;
                    degree[j]--;
                    if(degree[j]==1) q.push(j);
                }
            }
        }
        if(num<V) return true; //有环
        else return false;
    }
};

2.ユニオン検索セット
ユニオン検索セットは、一般にツリー構造を処理するために使用され、ツリーのエッジは有向エッジと見なすことができます。
グラフを処理する場合、圧縮できるのはパスのみであり、元のパスが失われるため、リングの存在のみを判断でき、リングを出力することはできません。
エッジに遭遇するたびに、結合が実行されます。リングがある場合、リングシールの端まで処理するとき、2つの頂点の父は同じです。

//邻接矩阵版
class Solution{
    
    
public:
    vector<int> father; //father存原始路径

    bool cyclic(vector<vector<int> >& graph){
    
    
        int V = graph.size();
        father.resize(V);
        for(int i=0; i<V; i++) father[i] = i;
        for(int i=0; i<V; i++){
    
    
            for(int j=0; j<V; j++){
    
    
                if(graph[i][j]!=0){
    
    
                    if(!union_set(i, j)) return true; //有环
                }
            }
        }
        return false;
    }

    int findFather(int a){
    
    
        int t = a;
        while(a!=father[a]) a = father[a];
        while(t!=father[t]){
    
    
            int u = father[t];
            father[t] = a;
            t = u;
        }
        return a;
    }

    bool union_set(int a, int b){
    
    
        int fa=findFather(a), fb=findFather(b);
        if(fa!=fb){
    
    
            father[fa] = fb;
            return true;
        }
        else return false; //出现环
    }
};

3、DFS

おすすめ

転載: blog.csdn.net/sinat_37517996/article/details/105059459