`

一个图是否存在环

 
阅读更多

问题描述:给一个图G=<V,E>,问如何判断这个图中是否存在回路?请给出至少3种方法

分析:

方法1:利用减枝的方法,

      如果G为有向图:

       1)首先删除入读为0的点,并且将对应的和该点相连的点的入读-1。(可以用一个数组表示节点被删除的状态)

       2)重复过程1),直到没有入读为0的点,如果还有没被删除的节点,则该有向图一定存在回路

      如果G为无向图:

       1)首先删除所有度数<=1的点,然后将与这些点相连的所有点的度数-1,然后将所有度数为1的点加入队列中

       2)对队列中的每个点,重复过程1),如果还有没被删除的节点,那么证明该图一定存在回路。

方法2:有向图)利用拓扑排序

      1)首先利用DFS[深度优先搜索算法]进行拓扑排序,最后生成一个拓扑序链表,然后为每个节点设置一个是否被访问过标记,用Visit数组

      2) 遍历这个链表,对每个节点v,设置visit[v]=1,如果判断如果存在与该节点相邻的节点u,使得Visit[u]=1,那么证明存在回边,这图中一定存在圈。

public class DirectedDepthFirstTopoWithCircleDetection  
{  
    private boolean[] visited;  
    // 用于记录dfs方法的调用栈,用于环路检测  
    private boolean[] onStack;  
    // 用于当环路存在时构造之  
    private int[] edgeTo;  
    private Stack<Integer> reversePost;  
    private Stack<Integer> cycle;  
  
    /** 
     * Topological Sorting Constructor 
     */  
    public DirectedDepthFirstTopoWithCircleDetection(Digraph di)  
    {  
        this.visited = new boolean[di.getV()];  
        this.onStack = new boolean[di.getV()];  
        this.edgeTo = new int[di.getV()];  
        this.reversePost = new Stack<Integer>();  
  
        for (int i = 0; i < di.getV(); i++)  
        {  
            if (!visited[i])  
            {  
                dfs(di, i);  
            }  
        }  
    }  
  
    private void dfs(Digraph di, int v)  
    {  
        visited[v] = true;  
        // 在调用dfs方法时,将当前顶点记录到调用栈中  
        onStack[v] = true;  
  
        for (int w : di.adj(v))  
        {  
            if(hasCycle())  
            {  
                return;  
            }  
            if (!visited[w])  
            {  
                edgeTo[w] = v;  
                dfs(di, w);  
            }  
            else if(onStack[w])  
            {  
                // 当w已经被访问,同时w也存在于调用栈中时,即存在环路  
                cycle = new Stack<Integer>();  
                cycle.push(w);  
                for(int start = v; start != w; start = edgeTo[start])  
                {  
                    cycle.push(v);  
                }  
                cycle.push(w);  
            }  
        }  
  
        // 在即将退出dfs方法时,将顶点添加到拓扑排序结果集中,同时从调用栈中退出  
        reversePost.push(v);  
        onStack[v] = false;  
    }  
  
    private boolean hasCycle()   
    {  
        return (null != cycle);  
    }  
      
    public Iterable<Integer> getReversePost()  
    {  
        if(!hasCycle())  
        {  
            return reversePost;  
        }  
        else   
        {  
            throw new IllegalArgumentException("Has Cycle: " + getCycle());  
        }  
    }  
      
    public Iterable<Integer> getCycle()   
    {  
        return cycle;  
    }  
}

 

 

方法3:无向图而言)利用BFS[广度优先搜索](利用算法导论上BFS的版本,每个节点有一个color属性,标记节点的颜色:“白”、“灰”、“黑”)

      1)直接利用BFS进行遍历,在判断当前节点的相邻的节点时,附加一个判断:如果这个节点的颜色为“灰色”,则return false,即存在环。

      2)遍历完所有的节点,返回true。

广度优先搜索算法示例,找V0到V6的最短路径:

 

 

方法4:无向图而言)还是利用BFS,在遍历过程中,为每个节点标记一个深度deep[],如果存在某个节点为v,除了其父节点u外,还存在与v相邻的节点w使得deep[v]<=deep[w]的,那么该图一定存在回路。

 

方法5:无向图而言)用BFS或DFS遍历,最后判断对于每一个连通分量当中,如果边数m>=节点个数n,那么改图一定存在回路。因此在DFS或BFS中,我们可以统计每一个连通分量的顶点数目n和边数m,如果m>=n则return false;直到访问完所有的节点,return true.

 

  • 大小: 62.7 KB
分享到:
评论

相关推荐

    判断有向图中是否存在环

    在计算机科学与图论中,判断一个有向图中是否存在环(cycle)是一项非常重要的任务。环是指在一个图中存在一条路径,该路径的起点和终点是同一个节点。如果一个有向图中存在环,则称其为非强连通图。本篇文章将详细...

    有向图的拓扑排序判断是否存在环

    在本场景中,我们讨论如何判断一个有向图是否存在环,并在无环的情况下进行拓扑排序。 首先,我们需要理解有向图的基本概念。有向图是由顶点(节点)和有方向的边组成的。边的方向决定了从一个顶点到另一个顶点的...

    图的拓扑排序和有向无环图的判断

    如果边是有方向的,即从一个顶点指向另一个顶点,那么这个图就被称为有向图。无环图意味着图中不存在任何从一个顶点出发经过若干边后又回到原点的路径。DAG是这两个特性的结合,即图中所有边都是有向的,且不存在环...

    算法—判断一个图是否是连接的;是否是树;是否有环,有环的话打印出来

    判断一个图是否连接通常可以使用深度优先搜索(DFS)算法。在DFS中,我们从任意一个节点开始,访问其所有相邻节点,然后继续访问这些相邻节点的未访问邻居,直到所有节点都被访问过。如果在过程中能够访问到所有...

    利用拓扑排序算法判别有向环

    拓扑排序是图论中的一个重要概念,特别是在计算机科学中,尤其是在数据结构和算法设计中有着广泛应用...通过DFS或BFS策略,可以在实践中快速判断一个有向图是否存在环,这对于理解和处理有向图结构的算法设计至关重要。

    有向图中是否存在环

    判别在用邻接表存储的有向图中是否存在环路。

    判断一个有向图中是否存在回路,并进行输出(拓扑算法)

    标题中的“判断一个有向图中是否存在回路,并进行输出(拓扑算法)”涉及到的是图论中的一个重要问题,即如何检测有向无环图(DAG,Directed Acyclic Graph)与有向图中的环。这个问题在计算机科学的多个领域都有...

    求一个无向图的最大环的边数(POJ3895) (java解答)

    标题中的“求一个无向图的最大环的边数(POJ3895)”是一个编程问题,来源于在线编程竞赛网站POJ(Programming Online Judge)。这个问题要求我们找出无向图中最大的环并计算其包含的边数。在无向图中,环是由若干个...

    jixianhuan.rar_MATLAB 极限环_cycle limit_matlab极限环_matlab画极限环_极限环

    标题中的“jixianhuan.rar”是一个压缩文件,它包含与MATLAB中处理极限环相关的资料。"MATLAB 极限环_cycle limit_matlab极限环_matlab画极限环_极限环"这部分描述了文件的主要内容,即如何使用MATLAB进行极限环的...

    算法导论生成一个100个点3000条边的有向无环图实验1-4

    有向图是由顶点和指向其他顶点的有向边组成的,而无环意味着图中不存在任何从一个顶点出发可以回到自身的路径。在DAG中,每个顶点可以被视为一个实体,每条边代表一个从一个实体到另一个实体的关系或流向。 生成...

    用dfs判断一个有向图是否有环1

    标题中的“用dfs判断一个有向图是否有环1”指的是使用深度优先搜索(DFS, Depth First Search)算法来检测有向图中是否存在环。在这个问题中,我们的目标是确定图中是否存在从某个节点出发能够回到自身(即形成环路...

    有向无环图拓扑排序并输出圈

    但如果图中存在环,则无法进行有效的拓扑排序,因为环意味着总会有一个节点在等待未完成的前驱节点,导致排序无法结束。 在"有向无环图拓扑排序并输出圈"的问题中,我们首先需要检查图是否为DAG。这通常通过DFS实现...

    Java版查找并打印有向图中的所有环路径

    另一方面,拓扑排序是将有向无环图(DAG)的顶点线性排列的一种方式,如果存在环,则无法进行拓扑排序,因此可以借此判断图中是否有环。 在`Graph.java`中,可能会有一个名为`detectCycle`的函数,它使用DFS进行...

    tuopu.rar_aov 检测环_aov网 判断有环_aov网检测环_topology 判断环

    在IT领域,特别是数据结构和算法的学习中,"拓扑排序"是一个重要的概念,它在处理有向无环图(Directed Acyclic Graph, DAG)时非常有用。标题和描述提到的"tuopu.rar_aov 检测环_aov网 判断有环_aov网检测环_...

    C#,图论与图算法,有向图(Directed Graph)的环(Cycle)的普通判断算法与源代码

    给定一个有向图,检查该图是否包含循环。如果给定的图形至少包含一个循环,则函数应返回true,否则返回false。 方法:深度优先遍历可用于检测图中的循环。连接图的DFS生成树。只有当图中存在后缘时,图中才存在循环...

    Java判断无向图中是否存在环

    在某些场景下,例如在路径查找或算法设计中,我们需要判断一个无向图中是否存在环。环是指在图中可以找到一条路径,这条路径从某个节点出发,经过一系列边,最终又回到了起点。 本问题中提到的Java代码实现了一个...

    判断给定有向图是否存在回路.zip_判定有向图是否存在回路

    有向图是图论中的一个基本概念,由若干个顶点和一些有序的顶点对(称为有向边或弧)组成,每条弧表示从一个顶点到另一个顶点的方向。在本问题中,我们需要判断给定的有向图是否存在回路。回路是指从某个顶点出发,...

    深度优先搜索输出有向图中的所有环(JAVA)

    在寻找环的过程中,我们可以利用一个布尔数组来记录每个顶点是否已经访问过,以及一个栈来保存当前的搜索路径。 以下是使用DFS寻找有向图环的步骤: 1. 初始化一个布尔数组`visited[]`,标记所有顶点为未访问。 2. ...

    vc实现的代码,能够找出图中所有的环

    邻接矩阵是一个二维数组,其中的元素表示对应节点之间是否存在边;邻接表则是一个链表结构,用于存储每个节点的所有邻接节点。对于较小的图,邻接矩阵简洁明了,但对大型稀疏图,邻接表更节省空间。 接下来,检测环...

    拓扑排序(还实现了有向图找环)

    3. 使用DFS进行拓扑排序,同时检查是否存在环。 4. 输出排序结果或者报告环的存在。 在实际编程中,还需要考虑一些细节,如错误处理、输入验证等。此外,邻接矩阵在空间效率上并不理想,对于大规模稀疏图,可以考虑...

Global site tag (gtag.js) - Google Analytics