-- adjacency list: adj[u] = {v1, v2, ...} local adj = {} local function add_edge(u, v) adj[u] = adj[u] or {} table.insert(adj[u], v) end -- Example graph add_edge("A", "B") add_edge("B", "C") add_edge("C", "D") -- Uncomment next line to introduce a cycle: add_edge("A", "D") --------------------------------------------------------- -- Topological sort (DFS-based, with cycle detection) --------------------------------------------------------- local visited = {} -- "perm" mark: node completely processed local in_stack = {} -- "temp" mark: node currently in recursion stack local order = {} -- reverse topological order local cycle = nil -- store cycle if found local function dfs(u, path) visited[u] = true in_stack[u] = true table.insert(path, u) for _, v in ipairs(adj[u] or {}) do if not visited[v] then dfs(v, path) if cycle then return end elseif in_stack[v] then -- found a cycle cycle = {} -- extract the cycle part from path for i = #path, 1, -1 do table.insert(cycle, 1, path[i]) if path[i] == v then break end end table.insert(cycle, v) -- close the cycle return end end in_stack[u] = false table.remove(path) table.insert(order, 1, u) end local function topo_sort() for u, _ in pairs(adj) do if not visited[u] then dfs(u, {}) if cycle then return nil, cycle end end end -- build rank map local rank = {} for i, u in ipairs(order) do rank[u] = i end return rank end --------------------------------------------------------- -- Run it --------------------------------------------------------- local rank, cycle = topo_sort() if cycle then print("Cycle detected:") print(table.concat(cycle, " -> ")) else print("Topological order ranks:") for k, v in pairs(rank) do print(k, v) end end