精华内容
下载资源
问答
  • 2.有向图 拓扑排序:用一个队列记录入度为0点,然后将他们去除时,另边另一头节点入度减一,不断记录入度为0点,若最后没有入度不为0点,则没有,否则有;不断插入队尾,循...

    1.无向图

    并查集:检查每一条边的两个端点是否是相同的连通子图,如果是相同的,说明存在环;

    深度遍历:使用邻接矩阵,只需要用一个数组标记是否访问过,如果访问过且不是该节点的父节点,则有环;

    广度优先:可以;

    2.有向图

    拓扑排序:用一个队列记录入度为0的点,然后将他们去除时,另边的另一头节点的入度减一,不断记录入度为0的点,若最后没有入度不为0的点,则没有环,否则有环;不断的插入队尾,循环;

    深度遍历:和无向图不同的是,我们不能直接和无向图的深度遍历一样,因为有可能出现,一个节点同时是2个节点的孩子节点,但这个时候不是环,所以需要去除标记,或者使用三种标记:0代表节点没有访问过,-1代表节点被访问过一次,但它还有孩子节点未被访问完,1代表该节点的深度遍历已经结束;这种方法比较巧妙,不需要去除标记;

    广度优先:不可以,深度优先记录的是经过的路径,环出现在经过的路径上;

     

    转载于:https://www.cnblogs.com/mdumpling/p/9494878.html

    展开全文
  • 有向图和无向图的环检测 1.无向图 可以用DFS检测,思想是,DFS过程,记录当前结点父结点,如果某结点以及访问过且不是该结点父结点,则存在

    有向图和无向图的环检测

    1.无向图

    深度优先搜索:思想是,DFS过程,记录当前结点的父结点,如果某结点以及访问过且不是该结点的父结点,则存在环

    并查集:如果两个结点存在一条边,判断两个结点的在并查集中的根结点是否相同,不相同则表明在不同的连通块,把他们union到一个连通块;

    否则,在遍历过程中发现如果某条边的两个结点都在一个连通块,则表明存在环

    package dfs;
    
    //冗余连接是指root[x] == root[y]
    class Solution684 {
    
        class Union{
            private int[] root;
            private int[] path;
            Union(int n){
                root = new int[n];
                path = new int[n];
                for(int i=0;i<n;i++){
                    root[i] = i;
                }
            }
            public boolean union(int x,int y){
                int rootX = find(x);
                int rootY = find(y);
                if(rootX==rootY){
                    return false;
                }
                if(path[rootX]<path[rootY]){        //将小树的根结点连接到大树的根结点
                    root[rootX] = rootY;
                    path[rootY] += 1;
                }else{
                    root[rootY] = rootX;
                    path[rootX] += 1;
                }
                return true;
            }
    
            public int find(int x){
                if(x != root[x]){
                    root[x] = find(root[x]);
                }
                return root[x];
            }
        }
    
        public int[] findRedundantConnection(int[][] edges) {
            int n = edges.length;
            Union ufind = new Union(n+1);       //结点是从1开始的所以加1
    
            for(int[] edge:edges){
                if(!ufind.union(edge[0],edge[1])){
                    return edge;
                }
            }
            return edges[0];
        }
    }
    
    public class lc684 {
        public static void main(String[] args) {
            int[][] edges = {{1,2},{1,3},{2,3}};
            Solution684 s = new Solution684();
            int[] res  = s.findRedundantConnection(edges);
            System.out.println(res[0]+" "+res[1]);
        }
    }
    
    /*
    c++版本
    class Solution {
    
        int u[2000];
    public:
        vector<int> findRedundantConnection(vector<vector<int>>& edges) {
            for(int i=0;i<edges.size();i++){
                u[i] = i;
            }
            vector<int> result(2,0);
            for(int i=0;i<edges.size();i++){
                vector<int> edge = edges[i];
                int root_x = find(edge[0]);
                int root_y = find(edge[1]);
    
                if(root_x == root_y){
                    result[0] = edge[0];
                    result[1] = edge[1];
                }else{
                    combine(edge[0],edge[1]);
                }
            }
            return result;
        }
    
        int find(int x){
            while(x!=u[x]){
                u[x] = u[u[x]];
                x = u[x];
            }
            return u[x];
        }
    
        void combine(int x,int y){
            u[find(x)] = find(y);
        }
    
    };
    * */

    2.有向图

    深度优先搜索:

    设置一个visited数组表示结点被访问过,如果在遍历过程中发现被访问过,则可能存在环;也存在被访问过但没有环的情况,所以需要借助栈,每当遍历一个结点,将结点推至栈中,结点是后进先出的,也就是

    如果环入口的结点会更靠近栈底,只有当结点被遍历过,且位于栈中,则判定有环;当该结点所有的邻居结点遍历完成,或者退回至该结点,将该结点出栈,这样做的目的是为了保证防止出现假的环

    package dfs;
    
    
    import java.util.ArrayList;
    import java.util.List;
    
    
    /*
    *       0  -   3
    *     /  \  \  |
    *    1 -  2   4
    * */
    
    class Solution207 {
        private List<Integer>[] g_list;
    
        //思路,用stack保存哪些结点在栈上,如果同时在栈上且被访问过,则有环
    
        public boolean canFinish(int numCourses, int[][] prerequisites) {
            boolean[] visited = new boolean[numCourses];
            boolean[] stack = new boolean[numCourses];
            g_list = new ArrayList[numCourses];
            //构建邻接表
            for(int i=0;i<numCourses;i++){
                g_list[i] = new ArrayList<>();
            }
            for(int[] z : prerequisites){
                g_list[z[0]].add(z[1]);
            }
    
            for(int i=0;i<numCourses;i++){
                if(!visited[i]){
                    if(dfs(i,visited,stack)){
                        return false;
                    }
                }
            }
            return true;
        }
        private boolean dfs(int v,boolean[] visited,boolean[] stack){
            visited[v] = true;
            stack[v] = true;
            for(int i : g_list[v]){
                if(visited[i] && stack[i]){
                    return true;
                }
                if(visited[i]) {
                    continue;
                }
                if(dfs(i,visited,stack)){
                    return true;
                }
            }
            stack[v] = false;
            return false;
        }
    }
    
    public class lc207 {
        public static void main(String[] args) {
            int numCourses = 2;
            int[][] prerequisites = new int[][]{{1,0}};
            Solution207 s = new Solution207();
            boolean res = s.canFinish(numCourses,prerequisites);
            System.out.println(res);
        }
    
    
    }
    

     

    展开全文
  • 将有向循环图转换为无图What to Learn?... 如何在有向图检测周期 ? In the following graph, 在下图中, It has a cycle 0-1-2-3-0 它具有一个周期0-1-2-3-0 (1-2-3-4-1 is not cycle since e...

    将有向循环图转换为无环图

    What to Learn?

    学什么?

    How to detect a cycle in a Directed graph?

    如何在有向图中检测周期

    In the following graph,

    在下图中,

    Cycle Detection in a Directed Graph

    It has a cycle 0-1-2-3-0

    它具有一个周期0-1-2-3-0

    (1-2-3-4-1 is not cycle since edge direction is 1->4, not 4->1)

    ( 1-2-3-4-1不是循环的,因为边缘方向是1-> 4 ,而不是4-> 1 )

    Algorithm:

    算法:

    Here we use a recursive method to detect a cycle in a graph.

    在这里,我们使用递归方法来检测图中的循环

    1. We check presence of a cycle starting by each and every node at a time.

      我们检查每个节点一次开始的循环是否存在。

    2. For each node

      对于每个节点

      1. Whenever we visited one vertex we mark it.
      2. Except the starting node, we go for all its adjacent nodes.
      3. If there is any marked vertex present that means there is a cycle present in the graph.
        Check(current node){
            visit[curr_node]=true;
            for( all the adjacent vertices ){
                if(not visited yet) then
                    check(adjacent vertex);
                else if( the vertex is already visited) then
                    There is a cycle in the graph
            }
        }
    
    

    C++ implementation:

    C ++实现:

    #include <bits/stdc++.h>
    using namespace std;
    
    void addedge(list<int>,int ,int );
    void cycle_check(list<int>*,int);
    
    //	Make a pair between vertex x and vertex y
    void addedge(list<int> *ls,int x,int y){
    	ls[x].push_back(y);
    	return;
    } 
    
    void check_cycle_util(list<int> *ls,bool *visit,int curr_node,int &temp){
    	visit[curr_node]=true;
    	list<int>::iterator it;
    	for(it=ls[curr_node].begin();it!=ls[curr_node].end();it++){
    		if(!visit[*it]){
    			check_cycle_util(ls,visit,*it,temp);
    		}
    		else{
    			if(temp==0){
    				temp=1;
    				cout<<"There is a cycle in the graph\n";
    				break;
    			}
    		}
    	}
    }
    //checking the cycles in a graph 
    void cycle_check(list<int>*ls,int num){
    	bool *visit=new bool[num];
    	int temp=0;
    	for(int i=0;i<num;i++)
    		visit[i]=false;
    	for(int i=0;i<num;i++){
    		if(!visit[i] && temp==0){
    			check_cycle_util(ls,visit,i,temp);
    		}
    	}
    }
    
    int main(){
    	int num;
    	cout<<"Enter the no. of vertices :";
    	cin>>num;
    	list<int> *ls=new list<int>[num];
    	addedge(ls,0,1);
    	addedge(ls,2,3);
    	addedge(ls,3,4);
    	addedge(ls,4,5);
    	addedge(ls,1,2);
    	addedge(ls,1,4);
    	addedge(ls,3,0);
    	cycle_check(ls,6);
    
    	return 0;
    }
    
    

    Output

    输出量

    Enter the no. of vertices : 6
    There is a cycle in the graph
    
    
    

    翻译自: https://www.includehelp.com/data-structure-tutorial/cycle-detection-in-a-directed-graph.aspx

    将有向循环图转换为无环图

    展开全文
  • 入度:有向图中某点作为图中边终点次数之和 出度: 对于有向图来说,顶点出边条数即为该顶点出度 调度系统中有向无图 数据调度系统中,多个任务之间依赖关系,用图可以表示,如下图所示,每个顶点表示...

    数据调度系统中有向无环图的无环检测

    名词解释

    • DAG,全称:Directed Acyclic Graph,中文:有向无环图
    • 入度:有向图中某点作为图中边的终点的次数之和
    • 出度: 对于有向图来说,顶点的出边条数即为该顶点的出度

    调度系统中的有向无环图

    数据调度系统中,多个任务之间的依赖关系,用图可以表示,如下图所示,每个顶点表示一个任务,箭头方向表示任务的执行顺序。任何顶点都无法经过边回到该顶点,则该图就是无环图,即为有向无环图(DAG图)。
    图1图1

    那么在有向图中,如果有环的存在,如图示:
    图2图2

    在有环的情况下,任务3的执行需要任务5完成,而5的执行又需要3,4依次执行完成,这样就会造成死循环,此调度任务永远无法成功执行。所以在调度系统中,对于无环的检测就非常重要。

    无环检测

    在调度系统中,检查图是否有环,分两种场景:1. 编辑图的过程中每一步操作都需要对其做无环检测;2. 对已经存在的图进行拓扑排序,检测是否有环。

    编辑时检测

    对于新创建的图来说,每增加一条边,都需要检测,这条边是否导致环的存在
    思路:如图1到图2, 如果要加一条5到3的边,就从3开始遍历后续顶点,如果能回到顶点5的话就证明新加的边导致环的产生;如果不能回到5,证明新添加的边不会导致有环。
    检测代码如下:

     /**
       * 判断增加边(fromVertex --> toVertex)是否合法,需要判断是否符合无环的约束
       *
       * @param fromVertex     起点
       * @param toVertex       终点
       * @param createVertex 是否创建结点
       * @return
       */
      private boolean isLegalAddEdge(Vertex fromVertex, Vertex toVertex, boolean isCreate) {
          if (fromVertex.equals(toVertex)) {
              logger.error("edge fromVertex({}) can't equals toVertex({})",fromVertex,toVertex);
              return false;
          }
          if (!isCreate) {
              if (!hasVertex(fromVertex) || !hasVertex(toVertex)){
                  logger.error("edge fromVertex({}) or toVertex({}) is not in vertices map",fromVertex,toVertex);
                  return false;
              }
          }
          Queue<Vertex> queue = new LinkedList<>();
          queue.add(toVertex);
          int verticesCount = getVerticesCount();
          //如果没有找到fromVertex, 表示无环;
          while (!queue.isEmpty() && verticesCount > 0) {
              verticesCount -= 1;
              Vertex key = queue.poll();
              // 遍历后续顶点
              for (Vertex subsequentVertex : getSubsequentNodes(key)) {
                  if (subsequentVertex.equals(fromVertex)) {
                      return false;
                  }
                  queue.add(subsequentVertex);
              }
          }
          return true;
      }
    

    拓扑排序检测

    有向图的拓扑排序,思路如下:

    1. 遍历图中所有的顶点,将入度为0的顶点入队列(如果多个顶点入度为0,取顶点顺序可能不一样,所以此处排序结果可能是多个)。
    2. 从队列中poll出一个顶点,更新该顶点的邻接点的入度(减1),如果邻接点的入度减1之后等于0,则将该邻接点入队列。
    3. 一直执行第2步,直到队列为空。
    4. 如果无法遍历完所有的结点,则意味着当前的图不是无环图。不存在拓扑排序。

    例如图1 入度出度:

    顶点 入度 出度
    顶点1 0 2
    顶点2 1 1
    顶点3 1 1
    顶点4 2 1
    顶点5 1 0

    拓扑排序流程如下:

    在这里插入图片描述

    java实现如下:

      /**
       * 判断是否有环及拓扑排序结果
       *
       * 有向无环图(DAG)才有拓扑(topological)排序
       * 广度优先遍历的主要做法:
       *    1、遍历图中所有的顶点,将入度为0的顶点入队列。
       *    2、从队列中poll出一个顶点,更新该顶点的邻接点的入度(减1),如果邻接点的入度减1之后等于0,则将该邻接点入队列。
       *    3、一直执行第2步,直到队列为空。
       * 如果无法遍历完所有的结点,则意味着当前的图不是有向无环图。不存在拓扑排序。
       *
       *
       * @return key返回的是状态, 如果成功(无环)为true, 失败则有环, value为拓扑排序结果(可能是其中一种)
       */
      private Map.Entry<Boolean, List<Vertex>> topologicalSortImpl() {
        //入度为0的结点队列
        Queue<Vertex> zeroIndegreeVertexQueue = new LinkedList<>();
        //保存结果
        List<Vertex> topoResultList = new ArrayList<>();
        //保存入度不为0的结点
        Map<Vertex, Integer> notZeroIndegreeVertexMap = new HashMap<>();
    
        //扫描所有的顶点,将入度为0的顶点入队列
        for (Map.Entry<Vertex, VertexInfo> vertices : verticesMap.entrySet()) {
          Vertex vertex = vertices.getKey();
          int inDegree = getIndegree(vertex);
    
          if (inDegree == 0) {
            zeroIndegreeVertexQueue.add(vertex);
            topoResultList.add(vertex);
          } else {
            notZeroIndegreeVertexMap.put(vertex, inDegree);
          }
        }
    
        //扫描完后,没有入度为0的结点,说明有环,直接返回
        if(zeroIndegreeVertexQueue.isEmpty()){
          return new AbstractMap.SimpleEntry(false, topoResultList);
        }
    
        //采用topology算法, 删除入度为0的结点和它的关联边
        while (!zeroIndegreeVertexQueue.isEmpty()) {
          Vertex v = zeroIndegreeVertexQueue.poll();
          //得到相邻结点
          Set<Vertex> subsequentNodes = getSubsequentNodes(v);
    
          for (Vertex subsequentVertex : subsequentNodes) {
    
            Integer degree = notZeroIndegreeVertexMap.get(subsequentVertex);
    
            if(--degree == 0){
              topoResultList.add(subsequentVertex);
              zeroIndegreeVertexQueue.add(subsequentVertex);
              notZeroIndegreeVertexMap.remove(subsequentVertex);
            }else{
              notZeroIndegreeVertexMap.put(subsequentVertex, degree);
            }
    
          }
        }
    
        //notZeroIndegreeVertexMap如果为空, 表示没有环
        AbstractMap.SimpleEntry resultMap = new AbstractMap.SimpleEntry(notZeroIndegreeVertexMap.size() == 0 , topoResultList);
        return resultMap;
    
      }
    
    }
    

    输出每个顶点的同时还要删除以它为起点的边。如果图有V个顶点,E条边,则一般该算法的时间复杂度为O(V+E)。这里实现的算法最终key返回的是状态, 如果成功(无环)为true, 失败则有环, 无环时value为拓扑排序结果(可能是其中一种)。

    展开全文
  • 有向图中有向环检测

    千次阅读 2018-01-02 10:55:08
    寻找有向图中是否存在有向环是判定一个任务优先级问题的前提边的类型从某个点开始的深度搜索过程中遇到了后向边,可作为找到有向环的标志代码实现private boolean[] onStack = new boolean[V];public void dfs(int s...
  • 向图有环检测

    千次阅读 2017-12-30 15:49:32
    问题给定一幅无向图,如何检测出其是否有环存在?//只需在深度优先搜索方法中添加几行代码即可解决 public void dfs(int v, int s) {//v代表要被搜索节点,s是v父节点,s->v,代表指向v一条路径, marked[v] ...
  • 基于有向环图和置信规则库网络入侵检测
  • class Item { private String name; private int helperInfo; public Item() { this.helperInfo = 0; } public Item(String name) { this.name = name; this.helperI...
  • 有向循环图转换为无图What you will learn?... 如何检测向图循环? In the graph below, 在下图中, It has cycles 0-1-4-3-0 or 0-1-2-3-0 它有个周期0-1-4-3-0或0-1-2-3-0 Algo...
  • 优先级限制下调度问题 给定一组需要完成任务,以及一组关于任务完成先后次序优先级限制。...有向图的环 一般来说,如果一个有优先级限制问题中存在有向,那么这个问题肯定是无解。要检查这种错误,需要
  • 检测有向图的环

    千次阅读 2015-03-17 02:38:40
    题目 http://www.geeksforgeeks.org/detect-cycle-in-a-graph/ Java实现 import java.util.ArrayList; import java.util.HashSet; import java.util.List; ...class GraphNode { private List children = new ArrayL
  • 给定有向图,判断某一个顶点是否可以到达另一个顶点,或者从一个顶点集合出发是否可以到达另一个顶点。单点可达性以及多点可达性问题,其中多点可达性可以用来解决java GC中存活对象判断。 利用marked来标记dfs...
  • 带权有向图找到全部的环完整源码#include #include <vector> #include #include #include using namespace std;int V, E; int n;//带权有向图 map, vector, int , double>>> EWD;bool m
  • 拓扑排序+有向环图(DAG)的检测

    千次阅读 2014-10-31 22:15:39
    /*************************** ...$$拓扑排序方法也是有向环图检测的方法 ****************************/ /* 拓扑排序 dfs搜索 - 邻接表 可以判断一个是否有 */ #include #include #include usin
  • 在一些调度引擎中,调度任务往往存在依赖,而检测是否存在循环依赖,即有向图中是否存在是调度引擎职责。当然,也是面试中常遇到算法。今天为大家介绍用拓扑排序方法检测有向图中是否有。 出度和入度...
  • 给定有向图如上,是[1,3,4]。 思路:分别对每个点进行深度遍历,在遍历过程中,一旦发现当前要存入元素已经在祖先数组中时,就发现了,此时打印。当没有打印结果时就代表没有。 from collections import...
  • 有向环图

    千次阅读 2018-10-31 17:22:49
    在和有向图相关实际应用中,有向特别重要。 优先级限制下调度问题:给定一组需要完成任务,以及一组关于任务完成先后次序优先级限制。在满足限制条件前提下应该如何安排并完成所有任务? 对于任意一个...
  • ApacheSpark是专为大规模数据处理而设计快速通用计算引擎。Spark是一种与 Hadoop 相似开源集群计算环境,拥有Hadoop MapReduce所具有优点;但不同于MapReduce是——Job中间输出结果可以保存在内存中,从而...

空空如也

空空如也

1 2 3 4 5 ... 13
收藏数 243
精华内容 97
关键字:

有向图环的检测