package main import ( "fmt" ) func bfsShortestPath(graph map[int][]int, start int) map[int]int { dist := make(map[int]int) for node := range graph { dist[node] = -1 } dist[start] = 0 queue := []int{start} for len(queue) > 0 { current := queue[0] queue = queue[1:] for _, neighbor := range graph[current] { if dist[neighbor] == -1 { dist[neighbor] = dist[current] + 1 queue = append(queue, neighbor) } } } return dist } func main() { graph := map[int][]int{ 0: {1, 2}, 1: {0, 3}, 2: {0, 3, 4}, 3: {1, 2, 4}, 4: {2, 3}, } distances := bfsShortestPath(graph, 0) fmt.Println(distances) }
The BFS starts at node 0 with distance 0. Nodes 1 and 2 are directly connected, so distance 1. Nodes 3 and 4 are two edges away, so distance 2.
BFS explores nodes in layers: all nodes at distance 1, then distance 2, and so on. The first time BFS visits a node, it is via the shortest path.
func bfsBuggy(graph map[int][]int, start int) map[int]int { dist := make(map[int]int) queue := []int{start} dist[start] = 0 for len(queue) > 0 { current := queue[0] queue = queue[1:] for _, neighbor := range graph[current] { if dist[neighbor] == 0 { dist[neighbor] = dist[current] + 1 queue = append(queue, neighbor) } } } return dist }
The code uses dist[neighbor] == 0 to check if a node is unvisited. But the start node has distance 0, so other nodes with distance 0 are considered visited incorrectly. This causes wrong distances.
package main import ( "fmt" ) func bfsWithParent(graph map[int][]int, start int) (map[int]int, map[int]int) { dist := make(map[int]int) parent := make(map[int]int) for node := range graph { dist[node] = -1 parent[node] = -1 } dist[start] = 0 queue := []int{start} for len(queue) > 0 { current := queue[0] queue = queue[1:] for _, neighbor := range graph[current] { if dist[neighbor] == -1 { dist[neighbor] = dist[current] + 1 parent[neighbor] = current queue = append(queue, neighbor) } } } return dist, parent } func reconstructPath(parent map[int]int, start, end int) []int { path := []int{} current := end for current != -1 { path = append([]int{current}, path...) current = parent[current] } if len(path) > 0 && path[0] == start { return path } return []int{} } func main() { graph := map[int][]int{ 0: {1, 2}, 1: {0, 3}, 2: {0, 3, 4}, 3: {1, 2, 4}, 4: {2, 3}, } dist, parent := bfsWithParent(graph, 0) path := reconstructPath(parent, 0, 4) fmt.Println(path) }
The BFS visits node 2 before node 3 when exploring neighbors of 0. So the shortest path to 4 is 0 -> 2 -> 4.
BFS visits each vertex once and explores all edges from each vertex once, so total time is proportional to vertices plus edges.
