• 判断有向图是否有环


    如何判断有向图是否有环

    • 1.dfs,bfs
    • 2.拓扑排序

    使用拓扑排序来解决这个问题,首先什么是拓扑排序?一直删除出度为0的顶点直到没有出度为0的顶点,如果最终还有顶点存在就说明有环,并且是由剩下的顶点组成的环。

    例如 有有向图的邻接表如下

    0->1
    1->0
    1->2
    2->3
    

    首先 3这个顶点出度为 0那先删除跟3有关的邻接表,剩下的邻接表有

    0->1
    1->0
    1->2
    

    然后 2这个顶点出度为0,删除跟2有关的邻接表,剩下的邻接表有

    0->1
    1->0
    

    已经没有出度为0的邻接表了,剩下的0,1组成了有向图的环

    代码实现

    // 有向图是否有环
    func canFinish(numCourses int, prerequisites [][]int) bool {
       // 邻接表map
    	adj := make(map[int]map[int]struct{}, numCourses)
    	// 反向邻接表map
    	adjR := make(map[int]map[int]struct{}, numCourses)
    	for i := 0; i < len(prerequisites); i++ {
    		_, ok := adj[prerequisites[i][1]]
    		if !ok {
    			adj[prerequisites[i][1]] = make(map[int]struct{}, numCourses)
    
    		}
    		_, ok = adjR[prerequisites[i][0]]
    		if !ok {
    			adjR[prerequisites[i][0]] = make(map[int]struct{}, numCourses)
    		}
    		adj[prerequisites[i][1]][prerequisites[i][0]] = struct{}{}
    		adjR[prerequisites[i][0]][prerequisites[i][1]] = struct{}{}
    
    	}
    	// 所有顶点集合map
    	g := make(map[int]struct{}, numCourses)
    	for i := 0; i < numCourses; i++ {
    		g[i] = struct{}{}
    	}
    	return !topology(adj, adjR, g)
    }
    
    // 图的拓扑排序  一直删除出度为0的顶点直到所有顶点出度大于0或者没有顶点了
    func topology(adj, adjR map[int]map[int]struct{}, g map[int]struct{}) bool {
    	var existsZero bool
    	for k := range g {
    		// 出度为0 删除这个节点
    		if _, ok := adj[k]; !ok {
    			existsZero = true
    			delete(g, k)
    			mr, ok1 := adjR[k]
    			if ok1 {
    				for i := range mr {
    					delete(adj[i], k)
    					if len(adj[i]) == 0 {
    						delete(adj, i)
    					}
    				}
    
    				delete(adjR, k)
    			}
    		}
    
    	}
    
    	if len(g) > 0 && existsZero {
    		return topology(adj, adjR, g)
    	}
    
    	if len(g) > 0 && !existsZero {
    		return true
    	}
    
    	return false
    }
  • 相关阅读:
    VSCODE极简配置(备份)
    顺时针打印矩阵--剑指offer
    回文链表 leetcode
    E
    E. Kleof&#225;š and the n-thlon
    单调栈板子
    D
    CodeForces 600E Lomsat gelral(线段树合并)
    C# 面试宝典
    JavaScript 火花效果
  • 原文地址:https://www.cnblogs.com/fwdqxl/p/10087372.html
Copyright © 2020-2023  润新知