| // Copyright 2026 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package graph |
| |
| import "slices" |
| |
| // SCCs computes the strongly connected components of the graph g. |
| func SCCs[NodeID comparable](g Graph[NodeID]) [][]NodeID { |
| // Use Kosaraju's algorithm. Tarjan is overkill here. |
| |
| // Forward pass |
| S := Postorder(g) |
| |
| // Reverse pass |
| gt := Transpose(g) |
| seen := make(map[NodeID]bool) |
| var scc []NodeID |
| var sccs [][]NodeID |
| var rvisit func(NodeID) |
| rvisit = func(u NodeID) { |
| if !seen[u] { |
| seen[u] = true |
| scc = append(scc, u) |
| for v := range gt.Out(u) { |
| rvisit(v) |
| } |
| } |
| } |
| for _, root := range slices.Backward(S) { |
| if !seen[root] { |
| scc = nil |
| rvisit(root) |
| sccs = append(sccs, scc) |
| } |
| } |
| return sccs |
| } |