| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 | 
							- package toposort
 
- // Copied from https://github.com/philopon/go-toposort
 
- type Graph struct {
 
- 	nodes   []string
 
- 	outputs map[string]map[string]int
 
- 	inputs  map[string]int
 
- }
 
- func NewGraph() *Graph {
 
- 	return &Graph{
 
- 		nodes:   []string{},
 
- 		inputs:  map[string]int{},
 
- 		outputs: map[string]map[string]int{},
 
- 	}
 
- }
 
- func (g *Graph) AddNode(name string) bool {
 
- 	g.nodes = append(g.nodes, name)
 
- 	if _, ok := g.outputs[name]; ok {
 
- 		return false
 
- 	}
 
- 	g.outputs[name] = make(map[string]int)
 
- 	g.inputs[name] = 0
 
- 	return true
 
- }
 
- func (g *Graph) AddNodes(names ...string) bool {
 
- 	for _, name := range names {
 
- 		if ok := g.AddNode(name); !ok {
 
- 			return false
 
- 		}
 
- 	}
 
- 	return true
 
- }
 
- func (g *Graph) AddEdge(from, to string) bool {
 
- 	m, ok := g.outputs[from]
 
- 	if !ok {
 
- 		return false
 
- 	}
 
- 	m[to] = len(m) + 1
 
- 	g.inputs[to]++
 
- 	return true
 
- }
 
- func (g *Graph) unsafeRemoveEdge(from, to string) {
 
- 	delete(g.outputs[from], to)
 
- 	g.inputs[to]--
 
- }
 
- func (g *Graph) RemoveEdge(from, to string) bool {
 
- 	if _, ok := g.outputs[from]; !ok {
 
- 		return false
 
- 	}
 
- 	g.unsafeRemoveEdge(from, to)
 
- 	return true
 
- }
 
- func (g *Graph) Toposort() ([]string, bool) {
 
- 	L := make([]string, 0, len(g.nodes))
 
- 	S := make([]string, 0, len(g.nodes))
 
- 	for _, n := range g.nodes {
 
- 		if g.inputs[n] == 0 {
 
- 			S = append(S, n)
 
- 		}
 
- 	}
 
- 	for len(S) > 0 {
 
- 		var n string
 
- 		n, S = S[0], S[1:]
 
- 		L = append(L, n)
 
- 		ms := make([]string, len(g.outputs[n]))
 
- 		for m, i := range g.outputs[n] {
 
- 			ms[i-1] = m
 
- 		}
 
- 		for _, m := range ms {
 
- 			g.unsafeRemoveEdge(n, m)
 
- 			if g.inputs[m] == 0 {
 
- 				S = append(S, m)
 
- 			}
 
- 		}
 
- 	}
 
- 	N := 0
 
- 	for _, v := range g.inputs {
 
- 		N += v
 
- 	}
 
- 	if N > 0 {
 
- 		return L, false
 
- 	}
 
- 	return L, true
 
- }
 
 
  |