判斷有向圖是否有環


如何判斷有向圖是否有環

  • 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
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM