package main

import "fmt"

// prereqs记录了每个课程的前置课程
var prereqs = map[string][]string{
	"algorithms": {"data structures"},
	// ---环---
	"linear algebra": {"calculus"},
	"calculus":       {"linear algebra"},
	// ---环---
	"compilers": {
		"data structures",
		"formal languages",
		"computer organization",
	},
	"data structures":       {"discrete math"},
	"databases":             {"data structures"},
	"discrete math":         {"intro to programming"},
	"formal languages":      {"discrete math"},
	"networks":              {"operating systems"},
	"operating systems":     {"data structures", "computer organization"},
	"programming languages": {"data structures", "computer organization"},
}

// hasCycle 检查图中是否存在环
func hasCycle(m map[string][]string) bool {
	// visited 记录已经访问过的节点
	visited := make(map[string]bool)
	// dfs 函数用来进行深度优先搜索
	var dfs func(string, map[string]bool) bool
	dfs = func(item string, path map[string]bool) bool {
		// 如果当前节点已经被访问过，则返回 false
		if visited[item] {
			return false
		}
		// 将当前节点标记为已访问，并加入访问路径
		visited[item] = true
		path[item] = true
		// 遍历当前节点的所有相邻节点
		for _, next := range m[item] {

			// 如果相邻节点已经在访问路径上，说明存在环，返回 true
			if path[next] || dfs(next, path) {
				return true
			}
		}
		// 将当前节点从访问路径中移除，并返回 false
		delete(path, item)
		return false
	}
	// 遍历 map 中的每个节点，并调用 dfs 函数检查是否存在环
	for k := range m {
		path := make(map[string]bool)
		if dfs(k, path) {
			return true
		}
	}
	// 如果所有节点都检查完，则说明图中不存在环，返回 false
	return false
}
func main() {
	// 有环则输出true
	fmt.Println(hasCycle(prereqs))
}
