无向图是否有环

判断无向图中是否存在回路(环)的算法描述

如果存在回路,则必存在一个子图,是一个环路。环路中所有顶点的度>=2。

算法:

第一步:删除所有度<=1的顶点及相关的边,并将另外与这些边相关的其它顶点的度减一。

第二步:将度数变为1的顶点排入队列,并从该队列中取出一个顶点重复步骤一。

如果最后还有未删除顶点,则存在环,否则没有环。

算法分析:

由于有m条边,n个顶点。如果m>=n,则根据图论知识可直接判断存在环路

(证明:如果没有环路,则该图必然是k棵树 k>=1。根据树的性质,边的数目m = n-k。k>=1,所以:m<n)

如果m<n 则按照上面的算法每删除一个度为0的顶点操作一次(最多n次),或每删除一个度为1的顶点(同时删一条边)操作一次(最多m次)。这两种操作的总数不会超过m+n。由于m<n,所以算法复杂度为O(n)

==============================================================================

==============================================================================

【有向图是否有环】【http://blog.csdn.net/insistgogo/article/details/6978718

有详细具体代码

==============================================================================

主要有深度优先和拓扑排序2中方法

1、拓扑排序,如果能够用拓扑排序完成对图中所有节点的排序的话,就说明这个图中没有环,而如果不能完成,则说明有环。

2、可以用Strongly Connected Components来做,我们可以回忆一下强连通子图的概念,就是说对于一个图的某个子图,该子图中的任意u->v,必有v->u,则这是一个强连通子图。这个限定正好是环的概念。所以我想,通过寻找图的强连通子图的方法应该可以找出一个图中到底有没有环、有几个环。

3、就是用一个改进的DFS

刚看到这个问题的时候,我想单纯用DFS就可以解决问题了。但细想一下,是不能够的。如果题目给出的是一个无向图,那么OK,DFS是可以解决的。但有向图得不出正确结果的。比如:A->B,A->C->B,我们用DFS来处理这个图,我们会得出它有环,但其实没有。

我们可以对DFS稍加变化,来解决这个问题。解决的方法如下:

图中的一个节点,根据其C[N]的值,有三种状态:

0,此节点没有被访问过

-1,被访问过至少1次,其后代节点正在被访问中

1,其后代节点都被访问过。

按照这样的假设,当按照DFS进行搜索时,碰到一个节点时有三种可能:

1、如果C[V]=0,这是一个新的节点,不做处理

2、如果C[V]=-1,说明是在访问该节点的后代的过程中访问到该节点本身,则图中有环。

3、如果C[V]=1,类似于2的推导,没有环。    在程序中加上一些特殊的处理,即可以找出图中有几个环,并记录每个环的路径

上面这个算法我没看懂。。所以没实现,但是自己用DFS实现了环检测。

  1. // DFS,发现回路(返回true)则不可序列化,返回false
  2. for (int i = 1; i <= n; i++) {
  3. if (dfsCheckCircuit(i))
  4. return false;
  5. }
  6. // 如果发现回路则返回true,否则遍历结束返回false
  7. private boolean dfsCheckCircuit(int current) {
  8. if (walked[current]) {
  9. return true;
  10. }
  11. walked[current] = true;
  12. for (int i = 1; i <= n; i++)
  13. if (digraph[current][i]) {
  14. if (dfsCheckCircuit(i)) {
  15. return true;
  16. }
  17. }
  18. walked[current] = false;
  19. return false;
  20. }
时间: 2024-10-03 22:40:08

无向图是否有环的相关文章

并查集(1)-判断无向图是否存在环

并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.常常在使用中以森林来表示.集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的元素所在的集合合并. Find:确定元素属于哪一个子集.它可以被用来确定两个元素是否属于同一子集合. Union:将两个子集合并成同一个集合. 其实判断一个图是否存在环已经有相应的算法,此文用并查集来判断一个图是否有环. 我们可以用一个一维数组parent[] 来记录子集合. 看下面这个图: 0 | | 1

无向图求三元环

http://acm.xidian.edu.cn/problem.php?id=1187 问题重述:给一个无向图,求其中包含 3 个结点的环的个数. 题解 暴力玄学,枚举边然后双指针扫描两个端点的邻集.注意用结点的顺序 关系去重,最后除以 3 会超时的.时间复杂度应该是 O(nm),不知道怎么过的. 网上 O(m√m) 的反而过不了. 注意如何避免除以三的遍历方式. 1 #include<cstdio> 2 #include<cstring> 3 #include<algor

cf290-2015-2-3总结与反思(dfs判断无向图是否有环)

bool dfs(int i,int pre) { visit[i]=true; for(int j=1;j<=v;j++) if(g[i][j]) { if(!visit[j]) return dfs(j,i); else if(j!=pre) //如果访问过,且不是其父节点,那么就构成环 return false; } } 方法:从一个顶点出发深度优先遍历可遍历所有结点,并且没有环或只有n-1条边. 若判断有环:可以在遍历时记住父结点,v的子结点w已被访问,且不是结点v的父结点,则存在环.

有向/无向图中搜环

经常遇到一类问题,提供一个图,判断其中是否含环.所谓的环是一条起点与终点相同的路径(至少含有一条边,两个结点).由于不带环的连通图和带环的连通图有着本质的区别,不带环的连通图是树,而树相较于一般的图可以支持更多更高效的算法,比如log2(n)时间复杂度内找任意两点的路径信息,在树上进行树形DP等等. 图按照边是否有向可以分为有向图和无向图.在两类图中找环的时间复杂度均为O(n),而判断是否含环的时间复杂度也是O(n),因此只陈述找环的方法. 无向图找环 无向图找环,因为无向图中没有明确的根,我们

[hdu5215]无向图找奇偶环

题意:如标题 思路:对于奇环,一个二分图判定就ok了,有奇环<=>非二分图.对于偶环,考虑环必定出现在双联通分量里面,可以先求出图的双联通分量,对于一个双联通分量,对于双联通分量里面的每个环,如果是偶环,则偶环已找到,否则假定存在多个奇环,则可以任选两个奇环,把共享边去掉,一定可以得到一个新偶环,这种情况下偶环也是存在的.所以不存在偶环的情况只可能是双联通分量是一个大奇环,特点是:边数=点数,且为奇.于是先dfs一下标记所有桥,用并查集标记所有双联通分量,对每个双联通分量,计算它的点数,对每条

无向图的最短环(需要输出路径)

参考代码:https://blog.csdn.net/yo_bc/article/details/75042688 POJ-1734 1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int MAX = 100+9; 5 const int _inf = 0x7fffffff; 6 const int INF = _inf/3;//可能会出现三个inf相加 7 8 int n,m; 9 i

无向图输出所有环。。【GYN给的题目和模型都错了。。。】

昨晚和今早帮GYN巧了一个小的算法 他的本意是把一个图的单环全部输出出来 结果建图的时候就出现问题了.. 应该是做一下修改就可以 但是我现在让他搞得目的都不知道干啥了.. 代码先放着 回去他跟我说了题意我在改 [这个要是写成了  也算是我项目上的第一个助攻了   哈哈] 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cmath> 5 #include &l

UVA10305 Ordering Tasks(有向无环图排序--toposort) Kahn算法

题目描述:https://vjudge.net/problem/UVA-10305 题目分析: 恨水的题目,只要学了toposort就会做的,大概意思是给你n个变量,m个不等关系表示a<b,问n个数可能的关系;不如举个例子例如n=3表示3个变量我们假如他们是a,b,c现在有两个关系a<b,a<c 那么输出有两种a<b<c或者a<c<b(题目要求输出任意一种); 题目大概就这个意思,那么我们怎么做呢,我们想一想如果把变量看成点,关系看成有向边,那么就得到一个图,这个

黑科技之三元环讲解

三元环是一个不怎么常见的黑科技,它的求解方法是一种基于分块思想的方法,比较简单好写,在这里介绍一下三元环的计数方法及正确性与时间复杂度证明. 对于一个n个点m条边的无向图,三元环是指对于图上的三个点,两两点之间都直接有边相连,这三个点组成的环就是三元环. 三元环的计数方法:记录图中每个点的度数,对于每条边将它定向.对于一条边,将度数大的点指向度数小的点,如果度数相同就将编号小的点指向编号大的点.计数时枚举每个点,对于每个点x枚举它的出边,并将出边指向的点y打标记,对于所有出边指向的点y再枚举出边