|
| 1 | +package graph |
| 2 | + |
| 3 | +import "container/heap" |
| 4 | + |
| 5 | +// Edge represents an edge in the graph |
| 6 | +type PointsEdge struct { |
| 7 | + u, v int |
| 8 | + weight int |
| 9 | +} |
| 10 | + |
| 11 | +// PriorityQueue implements heap.Interface and holds Edges |
| 12 | +type PriorityQueue []*PointsEdge |
| 13 | + |
| 14 | +func (pq PriorityQueue) Len() int { return len(pq) } |
| 15 | + |
| 16 | +func (pq PriorityQueue) Less(i, j int) bool { |
| 17 | + return pq[i].weight < pq[j].weight |
| 18 | +} |
| 19 | + |
| 20 | +func (pq PriorityQueue) Swap(i, j int) { |
| 21 | + pq[i], pq[j] = pq[j], pq[i] |
| 22 | +} |
| 23 | + |
| 24 | +func (pq *PriorityQueue) Push(x interface{}) { |
| 25 | + item := x.(*PointsEdge) |
| 26 | + *pq = append(*pq, item) |
| 27 | +} |
| 28 | + |
| 29 | +func (pq *PriorityQueue) Pop() interface{} { |
| 30 | + old := *pq |
| 31 | + n := len(old) |
| 32 | + item := old[n-1] |
| 33 | + *pq = old[0 : n-1] |
| 34 | + return item |
| 35 | +} |
| 36 | + |
| 37 | +func MinCostToConnectAllPoints(points [][]int) int { |
| 38 | + // Special case |
| 39 | + if len(points) == 0 { |
| 40 | + return 0 |
| 41 | + } |
| 42 | + // Total number of points |
| 43 | + n := len(points) |
| 44 | + // Array to store visited nodes |
| 45 | + visited := make([]bool, n) |
| 46 | + for i := range visited { |
| 47 | + visited[i] = false |
| 48 | + } |
| 49 | + // We need to visit only n - 1 vertices as we don't want |
| 50 | + // cycle in the graph |
| 51 | + edgesLeftToVisit := n - 1 |
| 52 | + // Total cost of connecting points |
| 53 | + cost := 0 |
| 54 | + // Since we always want nearest edge to be chosen first, |
| 55 | + // we will use minHeap to store edges by distances |
| 56 | + edges := &PriorityQueue{} |
| 57 | + heap.Init(edges) |
| 58 | + // We will choose first vertex 0 to find cost to reach all |
| 59 | + // points from here |
| 60 | + for i := 1; i < n; i++ { |
| 61 | + distance := Abs(points[i][0]-points[0][0]) + Abs(points[i][1]-points[0][1]) |
| 62 | + heap.Push(edges, &PointsEdge{u: 0, v: i, weight: distance}) |
| 63 | + } |
| 64 | + // Mark 0 node as visited |
| 65 | + visited[0] = true |
| 66 | + // Process edges until edgesLeftToVisit becomes 0 |
| 67 | + for edges.Len() > 0 && edgesLeftToVisit > 0 { |
| 68 | + // Get current edge |
| 69 | + edge := heap.Pop(edges).(*PointsEdge) |
| 70 | + v, weight := edge.v, edge.weight |
| 71 | + if !visited[v] { |
| 72 | + // Add the cost and mark as visited |
| 73 | + cost += weight |
| 74 | + visited[v] = true |
| 75 | + // Now traverse all possible points from v |
| 76 | + for i := 0; i < n; i++ { |
| 77 | + if !visited[i] { |
| 78 | + distance := Abs(points[i][0]-points[v][0]) + Abs(points[i][1]-points[v][1]) |
| 79 | + heap.Push(edges, &PointsEdge{u: v, v: i, weight: distance}) |
| 80 | + } |
| 81 | + } |
| 82 | + edgesLeftToVisit-- |
| 83 | + } |
| 84 | + } |
| 85 | + return cost |
| 86 | +} |
| 87 | + |
| 88 | +func Abs(a int) int { |
| 89 | + if a < 0 { |
| 90 | + return -a |
| 91 | + } |
| 92 | + return a |
| 93 | +} |
0 commit comments