-
Notifications
You must be signed in to change notification settings - Fork 10
/
bellmanford.go
60 lines (51 loc) · 1.23 KB
/
bellmanford.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package graphs
import "math"
type bellmanFordNode[T Vertex] struct {
cost float64
predecessor *T
}
// BellmanFord implements the Bellman-Ford algorithm. It returns
// the shortest-weight path from start to end vertex as a slice,
// or nil if the graph contains a negative-weight cycle.
func BellmanFord[T Vertex](g *Graph[T], start, end T) []T {
nodes := map[T]*bellmanFordNode[T]{}
g.EachVertex(func(v T, _ func()) {
nodes[v] = &bellmanFordNode[T]{
cost: math.Inf(1),
predecessor: nil,
}
})
nodes[start].cost = 0
n := g.NVertices()
for i := 0; i < n-1; i++ {
g.EachEdge(func(e Edge[T], _ func()) {
c := nodes[e.Start].cost + e.Cost
if c < nodes[e.End].cost {
nodes[e.End].cost = c
start := e.Start
nodes[e.End].predecessor = &start
}
})
}
// Check for negative-weight cycles.
hasNegativeWeightCycle := false
g.EachEdge(func(e Edge[T], stop func()) {
if nodes[e.Start].cost+e.Cost < nodes[e.End].cost {
hasNegativeWeightCycle = true
stop()
}
})
if hasNegativeWeightCycle {
return nil
}
i := 0
for v := &end; v != nil; v = nodes[*v].predecessor {
i++
}
path := make([]T, i)
for v := &end; v != nil; v = nodes[*v].predecessor {
i--
path[i] = *v
}
return path
}