如何判断一个图是否有环

对于无向图

算法1

我们知道对于环1-2-3-4-1,每个节点的度都是2,基于此我们有如下算法(这是类似于有向图的拓扑排序):

求出图中所有顶点的度,

删除图中所有度<=1的顶点以及与该顶点相关的边,把与这些边相关的顶点的度减一

如果还有度<=1的顶点重复步骤2

最后如果还存在未被删除的顶点,则表示有环;否则没有环

时间复杂度为O(E+V),其中E、V分别为图中边和顶点的数目,这个算法我们稍后分析算法3的时候再分析。

算法2

深度优先遍历该图,如果在遍历的过程中,发现某个节点有一条边指向已经访问过的节点,并且这个已访问过的节点不是当前节点的父节点(这里的父节点表示dfs遍历顺序中的父节点),则表示存在环。但是我们不能仅仅使用一个bool数组来标志节点是否访问过。如下图

从节点1开始遍历-接着遍历2-接着遍历3,然后发现3有一条边指向遍历过的1,则存在环。但是回到1节点时,它的另一条边指向已访问过的3,又把这个环重复计算了一次。

我们按照算法导论22.3节深度优先搜索中,对每个节点分为三种状态,白、灰、黑。开始时所有节点都是白色,当开始访问某个节点时该节点变为灰色,当该节点的所有邻接点都访问完,该节点颜色变为黑色。那么我们的算法则为:如果遍历的过程中发现某个节点有一条边指向颜色为灰的节点,那么存在环。则在上面的例子中,回溯到1节点时,虽然有一条边指向已经访问过的3,但是3已经是黑色,所以环不会被重复计算。

下面的代码中visit数组的值分为0 1 2三种状态分别代表白色、灰色、黑色,调用函数dfs可以输出图中存在的所有环,图用邻接矩阵表示,如果两个节点之间没有边则对应的值为INT_MAX

void dfsVisit(vector<vector<int> >&graph, int node, vector<int>&visit,
               vector<int>&father)
{
    int n = graph.size();
    visit[node] = 1;
    //cout<<node<<"-\n";
    for(int i = 0; i < n; i++)
        if(i != node && graph[node][i] != INT_MAX)
        {
            if(visit[i] == 1 && i != father[node])//找到一个环
            {
                int tmp = node;
                cout<<"cycle: ";
                while(tmp != i)
                {
                    cout<<tmp<<"->";
                    tmp = father[tmp];
                }
                cout<<tmp<<endl;
            }
            else if(visit[i] == 0)
            {
                father[i] = node;
                dfsVisit(graph, i, visit, father);
            }
        }
    visit[node] = 2;
}

void dfs(vector<vector<int> >&graph)
{
    int n = graph.size();
    vector<int> visit(n, 0); //visit按照算法导论22.3节分为三种状态
    vector<int> father(n, -1);// father[i] 记录遍历过程中i的父节点
    for(int i = 0; i < n; i++)
        if(visit[i] == 0)
            dfsVisit(graph, i, visit, father);
}

算法时间复杂度也是O(E+V)

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索算法
, 节点
, 有向图
顶点
如何判断图是否有环、如何判断图中是否有环、判断有向图是否有环、判断图是否有环、判断图中是否有环,以便于您获取更多的相关知识。

时间: 2024-09-17 03:57:14

如何判断一个图是否有环的相关文章

算法-怎么用深度优先判断一个图是否连通

问题描述 怎么用深度优先判断一个图是否连通 有一个无向图,找到相应的边,去掉这条边这个图就不是连通的.求相应算法.在线等.作业题急! 解决方案 在图论中,连通图基于连通的概念.在一个无向图G中,若从顶点v_i到顶点v_j有路径相连(当然从v_j到v_i也一定有路径),则称v_i和v_j是连通的.如果G是有向图,那么连接v_i和v_j的路径中所有的边都必须同向.如果图中任意两点都是连通的,那么图被称作连通图. 所以问题的关键是使用深度优先判断缺少某一边后图中是否任意两点连通. 一个基本的思路如下:

判断一个图是否连通

个人总结一下: 总的来说,可以用DFS(O(v^2))和BFS(O(v+e))的思想都能实现,只要从一个点出发,然后判断是否能遍历完所有的点.还有就是Tarjan算法和GABOW算法,这个没研究过,据说很好用.   实现办法一:用Floyd算法,时间复杂度为O(v^3),时间复杂度较大. 实现办法二:拓扑排序(多用于有向图). 实现办法三:用BFS和visa[]标志数组,看看从一个点出发,是否能访问完所有的点. 实现办法四:用DFS,(思想和办法三相差无几,递归用while循环代替而已)核心代码

如何高效地计算出一个有向无环图中各个节点的祖先节点数和后代节点数?

问题描述 如何高效地计算出一个有向无环图中各个节点的祖先节点数和后代节点数? 数据量较大,希望复杂度尽量低.现在实现图的数据结构是用HashMap记录对应标号的节点,再分别对每个节点使用HashMap记录子节点.感谢!

PHP如何判断一个gif图片是否为动态图片(动画)

如何使用PHP来判断一个gif图片是否为动态图片(动画)?首先想到的是使用getimagesize()函数来看type值,发现都是gif,所以这个办法是不可行的.下面是作者在网上看到的一个函数,用来判断gif是否为动图的.贴出来和大家分享. /* * 判断图片是否为动态图片(动画) */ function isAnimatedGif($filename) { $fp=fopen($filename,'rb'); $filecontent=fread($fp,filesize($filename)

android-Android 如何判断一个View在屏幕上可见

问题描述 Android 如何判断一个View在屏幕上可见 Android 如何判断一个View在屏幕上可见 我的过滤条件是这样的: view.isEnabled() && view.isShown() && view.isClickable() 可是这样即使某个View在下层不可见 .或者不可点击也能通过条件 解决方案 需要隐藏时,设置View的visible,后面根据visible判断 解决方案二: View 是放在 Activity 中显示的,所以按 Activity

在Mac Linux上如何快速判断一个文件是否是恶意程序?

熟悉Mac/Linux的用户经常会使用命令行,如果遇到系统异常,如CPU使用率暴涨等,经常会使用top命令去定位到底是哪个程序出现了异常.找到相关程序后,由于许多用户自身没有安全背景或者不大懂得逆向,便无法去分析程序到底做了什么,不敢枉然kill掉程序.又如果文件夹下面无故多了非自己创建的程序,这时也不敢枉然删除.针对这一情况,本文介绍几种小技巧,让你快速判断一个程序是否是恶意样本. 1.使用file命令快速识别文件类型   如图使用file命令识别名为bashd的文件,从结果中可以看出这个文件

PHP判断一个gif图片是否为动态图片的方法_php技巧

本文实例讲述了PHP判断一个gif图片是否为动态图片的方法.分享给大家供大家参考.具体方法如下: 如何使用PHP来判断一个gif图片是否为动态图片(动画)?首先想到的是使用getimagesize()函数来看type值,发现都是gif,所以这个办法是不可行的.下面是作者在网上看到的一个函数,用来判断gif是否为动图的.贴出来和大家分享 例子如下: 复制代码 代码如下: /*  * 判断图片是否为动态图片(动画)  */ function isAnimatedGif($filename) {  $

判断一个关键词竞争激烈程度的七个维度

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 选关键词通常是seo工作展开的第一步,选择合适自己的关键词也是seo成功的重要因素,因为选的关键词太简单,没人搜索seo的工作就没有意义,选的关键词如果太激烈不符合自身的势力,seo工作做的太好可能也是徒劳,那么判断一个关键词的竞争激烈程度呢,主要从下面这七个方面: 1.该关键词的竞价数.参与竞价的网站越多,说明这个关键词做的人越多,竞价数是

用c++写了一个函数判断一个数组是否包含另一个数组 但是总是返回-1 请大神们帮忙看看错在哪里

问题描述 用c++写了一个函数判断一个数组是否包含另一个数组 但是总是返回-1 请大神们帮忙看看错在哪里 int substr_index( const char substr[], const char str[]) { int flag = -1; int sizeOfSubstr = sizeof(substr)/sizeof(char); int sizeOfStr = sizeof(str)/sizeof(char); for (int i = 0; i < sizeOfStr; i+