input: Write a python function to find the shortest path using Dijkstra's Algorithm.
  assert dijkstra([[0, 2, 0, 1, 0, 0, 0],
                   [2, 0, 3, 2, 0, 0, 0],
                   [0, 3, 0, 0, 7, 0, 0],
                   [1, 2, 0, 0, 3, 1, 0],
                   [0, 0, 7, 3, 0, 2, 1],
                   [0, 0, 0, 1, 2, 0, 2],
                   [0, 0, 0, 0, 1, 2, 0]], 0, 6, 7) == [0, 3, 5, 6]
  assert dijkstra([[0, 1, 4, 0, 0, 0],
                   [1, 0, 4, 2, 7, 0],
                   [4, 4, 0, 3, 5, 0],
                   [0, 2, 3, 0, 4, 6],
                   [0, 7, 5, 4, 0, 7],
                   [0, 0, 0, 6, 7, 0]], 0, 5, 6) == [0, 1, 3, 5]
  assert dijkstra([[0, 9, 0, 0, 0, 14, 15],
                   [9, 0, 24, 0, 0, 0, 0],
                   [0, 24, 0, 6, 2, 18, 19],
                   [0, 0, 6, 0, 11, 30, 0],
                   [0, 0, 2, 11, 0, 0, 16],
                   [14, 0, 18, 30, 0, 0, 5],
                   [15, 0, 19, 0, 16, 5, 0]], 1, 4, 7) == [1, 2, 4]
output: def dijkstra(graph, start, end, n):
      import heapq
      
      distances = [float('inf')] * n
      distances[start] = 0
      priority_queue = [(0, start)]
      previous_nodes = [-1] * n
      
      while priority_queue:
          current_distance, current_node = heapq.heappop(priority_queue)
          
          if current_distance > distances[current_node]:
              continue
          
          for neighbor, weight in enumerate(graph[current_node]):
              if weight != 0:
                  distance = current_distance + weight
                  if distance < distances[neighbor]:
                      distances[neighbor] = distance
                      heapq.heappush(priority_queue, (distance, neighbor))
                      previous_nodes[neighbor] = current_node
                      
      path = []
      current = end
      while current != -1:
          path.append(current)
          current = previous_nodes[current]
      
      return path[::-1]