3 // StronglyConnected returns the list of strongly connected components
4 // within the Graph g. This information is primarily used by this package
5 // for cycle detection, but strongly connected components have widespread
7 func StronglyConnected(g *Graph) [][]Vertex {
11 VertexIndex: make(map[Vertex]int, len(vs)),
13 for _, v := range vs {
14 // Recurse on any non-visited nodes
15 if acct.VertexIndex[v] == 0 {
16 stronglyConnected(&acct, g, v)
22 func stronglyConnected(acct *sccAcct, g *Graph, v Vertex) int {
23 // Initial vertex visit
24 index := acct.visit(v)
27 for _, raw := range g.DownEdges(v).List() {
28 target := raw.(Vertex)
29 targetIdx := acct.VertexIndex[target]
31 // Recurse on successor if not yet visited
33 minIdx = min(minIdx, stronglyConnected(acct, g, target))
34 } else if acct.inStack(target) {
35 // Check if the vertex is in the stack
36 minIdx = min(minIdx, targetIdx)
40 // Pop the strongly connected components off the stack if
41 // this is a root vertex
52 acct.SCC = append(acct.SCC, scc)
58 func min(a, b int) int {
65 // sccAcct is used ot pass around accounting information for
66 // the StronglyConnectedComponents algorithm
69 VertexIndex map[Vertex]int
74 // visit assigns an index and pushes a vertex onto the stack
75 func (s *sccAcct) visit(v Vertex) int {
77 s.VertexIndex[v] = idx
83 // push adds a vertex to the stack
84 func (s *sccAcct) push(n Vertex) {
85 s.Stack = append(s.Stack, n)
88 // pop removes a vertex from the stack
89 func (s *sccAcct) pop() Vertex {
94 vertex := s.Stack[n-1]
95 s.Stack = s.Stack[:n-1]
99 // inStack checks if a vertex is in the stack
100 func (s *sccAcct) inStack(needle Vertex) bool {
101 for _, n := range s.Stack {