【三种解法】判断有向图是否有环


前言

我们最常用的是topsort来判断是否有环,因为这个方法简单。

我去网上找了很多关于如何用dfs来判断的算法,可谓五花八门且很容易被hack掉。

以上,所以写这篇文章来总结一下我知道的且常用有效的三种判断方法。

(我在考研辅导书天勤DS上看到作者给出了另一种解法,但目前还未验证正确性)

方法一:DFS(1)

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

#include<bits/stdc++.h>
using namespace std;
const int N = 105;
vector<vector<int>> g(N);
bool isCyclicUtil(int v, bool vis[],bool recStack[])
{
    if (!vis[v])
    {
        vis[v] = recStack[v] = true;
        for(int i = 0;i < g[v].size();++ i)
        {
            if (!vis[g[v][i]] && isCyclicUtil(g[v][i], vis, recStack))
                return true;
            else if (recStack[g[v][i]])
                return true;
        }
    }
    recStack[v] = false;
    return false;
}
bool isCyclic(int n)
{
    bool vis[n],recStack[n];
    for(int i = 0;i < n;++ i)
        vis[i] = recStack[i] = false;
    for(int i = 0;i < n;++ i)
    {
        if (isCyclicUtil(i, vis, recStack))
            return true;
    }
    return false;
}
int main()
{
    int n,m;
    cin >> n >> m;
    for(int i = 0;i < m;++ i)
    {
        int from, to;
        cin >> from >> to;
        g[from].push_back(to);
    }
    cout << (isCyclic(n) ? "yes" : "no");
    return 0;
}
/*
input
output
*/

方法二:DFS(2)

参考:https://www.geeksforgeeks.org/detect-cycle-direct-graph-using-colors/

#include<bits/stdc++.h>
using namespace std;
const int N = 105;
vector<vector<int>> g(N);
bool isCyclicUtil(int v, int color[])
{
    color[v] = 0;
 
    for(int i = 0;i < g[v].size();++ i)
    {
        if (color[g[v][i]] == 0)
            return true;
 
        if (color[g[v][i]] == -1 && isCyclicUtil(g[v][i],color))
            return true;
    }
    color[v] = 1;
    return false;
}
bool isCyclic(int n)
{
    //白色-1 表示未访问过
    //灰色0 表示正在访问,也就是当前点在DFS遍历树中
    //黑色1 表示已经访问过了
    int color[n];
    for(int i = 0;i < n;++ i)
        color[i] = -1;
    for(int i = 0;i < n;++ i)
    {
        if (color[i] == -1)
        {
            if (isCyclicUtil(i, color))
                return true;
        }
    }
    return false;
}
int main()
{
    int n,m;
    cin >> n >> m;
    for(int i = 0;i < m;++ i)
    {
        int from, to;
        cin >> from >> to;
        g[from].push_back(to);
    }
    cout << (isCyclic(n) ? "yes" : "no");
    return 0;
}
/*
input
output
*/

方法三:topsort

#include<bits/stdc++.h>
using namespace std;
const int N = 105;
vector<vector<int>> g(N);
int in[N],n,m;
bool topSort()
{
    for(int i = 0;i < n;++ i)
    {
        for(int j = 0;j < g[i].size();++ j)
        {
            ++ in[g[i][j]];
        }
    }
    queue<int> q;
    for(int i = 0;i < n;++ i)
    {
        if(!in[i])
            q.push(i);
    }
    int sum = 0;
    while(!q.empty())
    {
        int vt = q.front();
        q.pop();
        ++ sum;
 
        for(int i = 0;i < g[vt].size();++ i)
        {
            -- in[g[vt][i]];
            if(!in[g[vt][i]])
                q.push(g[vt][i]);
        }
    }
    return sum == n ? false : true;
}
int main()
{
    cin >> n >> m;
    for(int i = 0;i < m;++ i)
    {
        int from, to;
        cin >> from >> to;
        g[from].push_back(to);
    }
    cout << (topSort() ? "yes" : "no");
    return 0;
}
/*
input
output
*/

方法四(?):DFS(3)

参考:天勤DS

#include<bits/stdc++.h>
using namespace std;
const int N = 105;
vector<vector<int>> g(N);
bool isCyclicUtil(int v, bool vis[])
{
    bool flag;
    vis[v] = true;
    for(int i = 0;i < g[v].size();++ i)
    {
        if (vis[g[v][i]])
            return true;
        else flag = isCyclicUtil(g[v][i], vis);
 
        if (flag)
            return true;
        vis[g[v][i]] = false;
    }
    return false;
}
bool isCyclic(int n)
{
    bool vis[n];
    for(int i = 0;i < n;++ i)
        vis[i] = false;
    for(int i = 0;i < n;++ i)
    {
        if (isCyclicUtil(i, vis))
            return true;
    }
    return false;
}
int main()
{
    int n,m;
    cin >> n >> m;
    for(int i = 0;i < m;++ i)
    {
        int from, to;
        cin >> from >> to;
        g[from].push_back(to);
    }
    cout << (isCyclic(n) ? "yes" : "no");
    return 0;
}
/*
input
output
*/

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM