強連結成分分解

Share:
 1type scc struct {
 2	g  [][]int
 3	rg [][]int
 4}
 5
 6func newStronglyConnectedComponents(n int) *scc {
 7	return &scc{make([][]int, n), make([][]int, n)}
 8}
 9
10func (s *scc) AddEdge(v, to int) {
11	s.g[v] = append(s.g[v], to)
12	s.rg[to] = append(s.rg[to], v)
13}
14
15func (s *scc) Scc() [][]int {
16	n := len(s.g)
17	vs := make([]int, 0, n)
18	vis := make([]bool, n)
19	cmp := make([]int, n)
20
21	var dfs func(v int)
22	dfs = func(v int) {
23		vis[v] = true
24		for _, to := range s.g[v] {
25			if !vis[to] {
26				dfs(to)
27			}
28		}
29		vs = append(vs, v)
30	}
31
32	var rdfs func(v, k int)
33	rdfs = func(v, k int) {
34		vis[v] = true
35		cmp[v] = k
36		for _, to := range s.rg[v] {
37			if !vis[to] {
38				rdfs(to, k)
39			}
40		}
41	}
42
43	for i := 0; i < n; i++ {
44		if !vis[i] {
45			dfs(i)
46		}
47	}
48
49	for i := 0; i < n; i++ {
50		vis[i] = false
51	}
52
53	k := 0
54	for i := len(vs) - 1; i >= 0; i-- {
55		if !vis[vs[i]] {
56			rdfs(vs[i], k)
57			k++
58		}
59	}
60
61	t := make([][]int, k)
62	for i := 0; i < n; i++ {
63		t[cmp[i]] = append(t[cmp[i]], i)
64	}
65
66	return t
67}
68