Detect Cycle In Directed/Undirected Graph

Detect Cycle in a Directed Graph

https://www.geeksforgeeks.org/detect-cycle-in-a-graph/

有向图里的环必须是 a->b b->c c->a 类似这种的环(包括自环)。

这学期刚上过算法,dfs遍历图会得到dfs tree(如果不是连通图就是forest),并提到了back edge的概念。如果dfs遍历图的时候,有back edge产生,那就说明一定有环。

 

写起来就按照标准的dfs写,需要一个visited数组来判断是否已经访问过。这里还需要一个set来记录递归过程中压栈的节点,以此判断是否是back edge。

注意不要想当然的直接用visited来判断,如果节点之前访问过就有环,这样是不过的,反例如 a->b->d a->c->d。

时间复杂度 O(V+E)

#include <iostream>
#include <vector>
#include <list>
#include <unordered_set>
using namespace std;

class DirectedGraph{
    int n; // # of nodes
    vector<list<int>> adj; // adjacency lists
public:
    DirectedGraph(int N):n(N),adj(N,list<int>()){};
    void addEdge(int u, int v){ // to add an edge u->v to graph
        adj[u].push_back(v);
    }
    bool isCyclic(){
        //If has back edge, then has cycle
        vector<bool> visited(n,false);
        unordered_set<int> recStack; // recursion stack
        
        for (int i=0;i<n;++i){
            if (dfs(i,visited,recStack)) 
                return true;
        }
        return false;
    }
    
    bool dfs(int i, vector<bool> &visited, unordered_set<int> &recStack){
        if (recStack.count(i)) return true;
        if (visited[i]) return false;
        
        visited[i] = true;
        recStack.insert(i);
        for (auto x:adj[i])
            if (dfs(x,visited,recStack))
                return true;
        
        recStack.erase(i);
        return false;
    }
};


int main() {
    DirectedGraph g(4);
    g.addEdge(0, 1); 
    //g.addEdge(0, 2); 
    g.addEdge(1, 2); 
    //g.addEdge(2, 0); 
    g.addEdge(2, 3); 
    //g.addEdge(3, 3); 
    cout << g.isCyclic();
    return 0;
}

 

 

Detect cycle in an undirected graph

https://www.geeksforgeeks.org/detect-cycle-undirected-graph/

无向图就简单很多,如果dfs的时候,当前节点的neighbor中有被访问过且不是parent的节点,就一定有环存在。

这里顺便复习一下dfs两种写法:1) dfs最开始判断边界条件  2) dfs前判断边界条件

由于需要dfs时判断是否是parent,dfs就不能写成 1) 的形式了,要写成 2) 的形式。

#include <iostream>
#include <vector>
#include <list>
#include <unordered_set>
using namespace std;

class UndirectedGraph{
    int n; // # of nodes
    vector<list<int>> adj; // adjacency lists
public:
    UndirectedGraph(int N):n(N),adj(N,list<int>()){};
    void addEdge(int u, int v){ // to add an edge u-v to graph
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    bool isCyclic(){
        //if visited before and not parent, then has cycle
        vector<bool> visited(n,false);
        
        for (int i=0;i<n;++i){
            if (!visited[i]){
                if (dfs(i,visited,-1))
                    return true;
            }
        }
        return false;
    }
    
    bool dfs(int i, vector<bool> &visited, int parent){
        visited[i] = true;
        for (auto x:adj[i]){
            if (visited[x] && x!=parent)
                return true;
            if (!visited[x]){
                if (dfs(x,visited,i))
                    return true;
            }
        }
        return false;
    }
};


int main() 
{ 
    UndirectedGraph g1(5); 
    g1.addEdge(1, 0); 
    g1.addEdge(0, 2); 
    g1.addEdge(2, 0); 
    g1.addEdge(0, 3); 
    g1.addEdge(3, 4); 
    g1.isCyclic()? cout << "Graph contains cycle\n": 
                  cout << "Graph doesn't contain cycle\n"; 
  
    UndirectedGraph g2(3); 
    g2.addEdge(0, 1); 
    g2.addEdge(1, 2); 
    g2.isCyclic()? cout << "Graph contains cycle\n": 
                   cout << "Graph doesn't contain cycle\n"; 
  
    return 0; 
} 

转载于:https://www.cnblogs.com/hankunyan/p/10962814.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值