def graph_distances(start, edges, distances):
    """
    Given an undirected adjacency list and a pairwise distance matrix between
    all nodes: calculates distances along graph from start node.

    Args:
        start (int): start node
        edges (list): adjacency list of tuples
        distances (array): 2d array of distances between nodes

    Returns:
        dict of node to distance from start
    """
    # convert adjacency list to adjacency dict
    adj = {x: [] for x in range(len(distances))}
    for n1, n2 in edges:
        adj[n1].append(n2)
        adj[n2].append(n1)
    # run dijkstra's algorithm
    to_visit = []
    new_dist = {}
    for n in adj[start]:
        heapq.heappush(to_visit, (distances[start, n], n))
    while to_visit:
        d, next_node = heapq.heappop(to_visit)
        if next_node not in new_dist:
            new_dist[next_node] = d
        for n in adj[next_node]:
            if n not in new_dist:
                heapq.heappush(to_visit, (d + distances[next_node, n], n))
    return new_dist
Given an undirected adjacency list and a pairwise distance matrix between
    all nodes: calculates distances along graph from start node.

    Args:
        start (int): start node
        edges (list): adjacency list of tuples
        distances (array): 2d array of distances between nodes

    Returns:
        dict of node to distance from start