code: def dijkstra_update_heap(graph, weight, source=0, target=None):
      
      n = len(graph)
      assert all(weight[u][v] >= 0 for u in range(n) for v in graph[u])
      prec = [None] * n
      dist = [float('inf')] * n
      dist[source] = 0
      heap = OurHeap([(dist[node], node) for node in range(n)])
      while heap:
          dist_node, node = heap.pop()       # Closest node from source
          if node == target:
              break
          for neighbor in graph[node]:
              old = dist[neighbor]
              new = dist_node + weight[node][neighbor]
              if new < old:
                  dist[neighbor] = new
                  prec[neighbor] = node
                  heap.update((old, neighbor), (new, neighbor))
      return dist, prec
docs: single source shortest paths by Dijkstra
         with a heap implementing item updates
  
         :param graph: adjacency list or adjacency dictionary of a directed graph
         :param weight: matrix or adjacency dictionary
         :assumes: weights are non-negatif and weights are infinite for non edges
         :param source: source vertex
         :type source: int
         :param target: if given, stops once distance to target found
         :type target: int
         :returns: distance table, precedence table
         :complexity: `O(|V| + |E|log|V|)`