如何判斷有向圖是否有環ui
使用拓撲排序來解決這個問題,首先什麼是拓撲排序?一直刪除出度爲0的頂點直到沒有出度爲0的頂點,若是最終還有頂點存在就說明有環,而且是由剩下的頂點組成的環。code
例如 有有向圖的鄰接表以下排序
0->1 1->0 1->2 2->3
首先 3這個頂點出度爲 0那先刪除跟3有關的鄰接表,剩下的鄰接表有it
0->1 1->0 1->2
而後 2這個頂點出度爲0,刪除跟2有關的鄰接表,剩下的鄰接表有map
0->1 1->0
已經沒有出度爲0的鄰接表了,剩下的0,1組成了有向圖的環top
代碼實現集合
// 有向圖是否有環 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 }