Advertisement
Guest User

Untitled

a guest
Aug 30th, 2016
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 6.00 KB | None | 0 0
  1. package main
  2.  
  3. import "fmt"
  4. import "container/heap"
  5.  
  6. // The graph will consist of a [][]*Edge, which is a 2D slice, the first [] dimension
  7. // is the number of nodes (thus each position represents a node) and then the second
  8. // []*Edge dimension represents a list of *Edge elements for each node (the edges)
  9. // that come out from that node towards another. Since it will be an undirected graph
  10. // the created *Edge will exist in both ends/nodes.
  11. type Edge struct {
  12.     from, to, cost int
  13. }
  14.  
  15. // PriorityQueue is a type for []*Edge, such that it will implement the heap
  16. // interface (Push, Pop) and its "inherited" sort interface (Len, Swap, Less)
  17. // Heap interface implementation referenced from:
  18. //     https://golang.org/pkg/container/heap/
  19. type PriorityQueue []*Edge
  20.  
  21. // Length of the PriorityQueue ([]*Edge).
  22. // Method is implemented as per Heap->Sort interface.
  23. func (pq PriorityQueue) Len() int {
  24.     return len(pq)
  25. }
  26.  
  27. // Swap two elements of the PriorityQueue and update indices in PQ.
  28. // Method is implemented as per Heap->Sort interface.
  29. func (pq PriorityQueue) Swap(i, j int) {
  30.     pq[i], pq[j] = pq[j], pq[i]
  31. }
  32.  
  33. // We want the PriorityQueue to prioritize items with lesser cost.
  34. // Method is implemented as per Heap->Sort interface.
  35. func (pq PriorityQueue) Less(i, j int) bool {
  36.     return pq[i].cost < pq[j].cost
  37. }
  38.  
  39. // Push a new element into the PriorityQueue.
  40. // Method is implemented as per Heap interface.
  41. func (pq *PriorityQueue) Push(e interface{}) {
  42.     edge := e.(*Edge)
  43.     *pq = append(*pq, edge)
  44. }
  45.  
  46. // Remove an element from the PriorityQueue
  47. // Method is implemented as per Heap interface.
  48. func (pq *PriorityQueue) Pop() interface{} {
  49.     oldpq := *pq
  50.     n := len(oldpq)
  51.     edge := oldpq[n-1]
  52.     *pq = oldpq[0 : n-1]
  53.     return edge
  54. }
  55.  
  56. // Dijkstra algorithm, which uses a PriorityQueue to find the shortest
  57. // path between two nodes, giving priority to the shortest paths coming
  58. // up in the PriorityQueue.
  59. func dijkstra(nodes [][]*Edge, start int) []int {
  60.     // Default value for costs is -1, this means unvisited. First visit
  61.     // will immediately replace it, and then we'll start looking for the
  62.     // lowest possible value.
  63.     costs := make([]int, len(nodes))
  64.     for i := 0; i < len(costs); i++ {
  65.         costs[i] = -1
  66.     }
  67.  
  68.     // Create a fake edge to the starting node, to start graph traversal from it
  69.     st := &Edge{
  70.         from: start,
  71.         to:   start,
  72.         cost: 0,
  73.     }
  74.     // The cost/path weight to reach the starting node will be zero.
  75.     costs[start] = 0
  76.     // Initialize the PriorityQueue and insert the fake edge to the 'root' node.
  77.     pq := PriorityQueue{}
  78.     heap.Init(&pq)
  79.     heap.Push(&pq, st)
  80.  
  81.     // While there are elements on the PriorityQueue...
  82.     for len(pq) > 0 {
  83.         // Pop the element from the PQ, and then assert its type to be *Edge
  84.         // since following Heap's interface requires elements to be interface{}
  85.         cur := heap.Pop(&pq).(*Edge)
  86.         // Iterate over all the edges outgoing from current node.
  87.         // The retrieved 'cur' is just an Edge inserted previously, the current
  88.         // node is the 'to' ~ target value of that Edge.
  89.         for i := 0; i < len(nodes[cur.to]); i++ {
  90.             edge := nodes[cur.to][i]
  91.             // If the cumulative cost to this point + the cost to a neighbor node
  92.             // is less than the registered value of the cost to that node, then
  93.             // add that path as a possibility and register new low cost value!
  94.             // Also push the edge if no cost has been ever registered towards the
  95.             // target node (meaning so far first value found will be stored).
  96.             if costs[edge.from]+edge.cost < costs[edge.to] || costs[edge.to] == -1 {
  97.                 costs[edge.to] = costs[edge.from] + edge.cost
  98.                 heap.Push(&pq, edge)
  99.             }
  100.         }
  101.     }
  102.     return costs
  103. }
  104.  
  105. func main() {
  106.     // t: is the number of test cases.
  107.     var t int
  108.     fmt.Scanf("%v", &t)
  109.     for i := 0; i < t; i++ {
  110.         // n: number of nodes in graph, m: number of edges in graph.
  111.         var n, m int
  112.         fmt.Scanf("%v %v", &n, &m)
  113.         // 1st dimension []: number of nodes
  114.         // 2nd dimension []*Edge: a list of Edges going out from the node at index i.
  115.         nodes := make([][]*Edge, n)
  116.         // We want to account for duplicated edges with a set-like map.
  117.         edgeMap := map[Edge]bool{}
  118.  
  119.         for j := 0; j < m; j++ {
  120.             var x, y, c int
  121.             // x, y, c, make an undirected edge in a graph.
  122.             fmt.Scanf("%v %v %v", &x, &y, &c)
  123.             // Make the node indices zero-indexed.
  124.             x, y = x-1, y-1
  125.             edgeToY := Edge{x, y, c}
  126.             edgeToX := Edge{y, x, c}
  127.             // The graph is undirected, so add edge in both node positions. Also,
  128.             // check that no such unique combination (from, to, cost) exists (so
  129.             // to remove duplicate entries). If there's an edge between two nodes
  130.             // with different cost, lets consider it a different edge.
  131.             if _, ok := edgeMap[edgeToY]; !ok {
  132.                 nodes[x] = append(nodes[x], &edgeToY)
  133.                 edgeMap[edgeToY] = true
  134.             }
  135.             if _, ok := edgeMap[edgeToX]; !ok {
  136.                 nodes[y] = append(nodes[y], &edgeToX)
  137.                 edgeMap[edgeToX] = true
  138.             }
  139.         }
  140.  
  141.         // s: the starting position.
  142.         var s int
  143.         fmt.Scanf("%v", &s)
  144.         // Dijkstra algorithm will return an array with the lowest possible
  145.         // distances to each node from a starting node (and -1 if its unreachable)
  146.         distances := dijkstra(nodes, s-1)
  147.  
  148.         for i := range distances {
  149.             // Don't print the starting location distance
  150.             if distances[i] != 0 {
  151.                 fmt.Printf("%v", distances[i])
  152.                 if i+1 < len(distances) {
  153.                     fmt.Printf(" ")
  154.                 } else {
  155.                     fmt.Printf("\n")
  156.                 }
  157.             }
  158.         }
  159.     }
  160. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement