最短路径问题的Dijkstra算法超出了Kattis时间限制

时间:2019-10-12 22:34:51

标签: python algorithm performance time shortest-path

我目前正在尝试解决:https://open.kattis.com/problems/shortestpath1,这是权重为正的最短路径问题,对Python来说我还很陌生。

我已经实现了算法和主要功能。对于第一个测试用例,它可以正常工作,但对于第二个用例,则超过了> 3s的时间限制,导致我的代码没有被接受为答案,而且我认为我的代码中有错误(并且实际上不是优化)错误,因为我认为3秒钟应该就足够了。

该如何改进我的代码,使其通过第二个测试用例?

from collections import deque, namedtuple

inf = float('inf')
Edge = namedtuple('Edge', 'start, end, cost')

def make_edge(start, end, cost=1):
    return Edge(start, end, cost)


class Graph:
def __init__(self, edges):
    self.edges = [make_edge(*edge) for edge in edges]

@property
def vertices(self):
    return set(
        sum(
            ([edge.start, edge.end] for edge in self.edges), []
        )
    )

def get_node_pairs(self, n1, n2, both_ends=True):
    if both_ends:
        node_pairs = [[n1, n2], [n2, n1]]
    else:
        node_pairs = [[n1, n2]]
    return node_pairs

def remove_edge(self, n1, n2, both_ends=True):
    node_pairs = self.get_node_pairs(n1, n2, both_ends)
    edges = self.edges[:]
    for edge in edges:
        if [edge.start, edge.end] in node_pairs:
            self.edges.remove(edge)

def add_edge(self, n1, n2, cost=1, both_ends=True):
    node_pairs = self.get_node_pairs(n1, n2, both_ends)
    #for edge in self.edges:
        #if [edge.start, edge.end] in node_pairs:
           #return ValueError('Edge {} {} already exists'.format(n1, n2))

    self.edges.append(Edge(start=n1, end=n2, cost=cost))
    if both_ends:
        self.edges.append(Edge(start=n2, end=n1, cost=cost))

@property
def neighbours(self):
    neighbours = {vertex: set() for vertex in self.vertices}
    for edge in self.edges:
        neighbours[edge.start].add((edge.end, edge.cost))

    return neighbours

def dijkstra(self, source, dest):
    #assert source in self.vertices, 'Such source node doesn\'t exist'
    distances = {vertex: inf for vertex in self.vertices}
    previous_vertices = {
        vertex: None for vertex in self.vertices
    }
    distances[source] = 0
    vertices = self.vertices.copy()

    while vertices:
        current_vertex = min(
            vertices, key=lambda vertex: distances[vertex])
        vertices.remove(current_vertex)
        if distances[current_vertex] == inf:
            break
        for neighbour, cost in self.neighbours[current_vertex]:
            alternative_route = distances[current_vertex] + cost
            if alternative_route < distances[neighbour]:
                distances[neighbour] = alternative_route
                previous_vertices[neighbour] = current_vertex

    #Deque er som list men med O(1) over O(N) for list.pop()
    path, current_vertex = deque(), dest
    while previous_vertices[current_vertex] is not None:
        path.appendleft(current_vertex)
        current_vertex = previous_vertices[current_vertex]
    if path:
        path.appendleft(current_vertex)
    #return path here to get the deque with path as list of strings
    #need the distance:
    d = 0
    for index in range(len(path)):
        for x in self.edges:
            if x.start == path[index-1] and x.end == path[index]:
                d += x.cost
    return d

if __name__ == "__main__":
    #edge1 = Edge("0", "1", 2)
    #edge2 = Edge("1", "2", 2)
    #testGraph2()
    #while dette får input..
    n, m, q, s = [0, 0, 0, 0]
    u, v, w = [0, 0, 0]
    while True:
        edges = []
        [n, m, q, s] = input().split()
        #print("n: ", n, "m: ",  m, "q", q, "s: ", s)
        if n == "0" and m == "0" and q == "0" and s == "0":
            break
        for i in range(int(m)):
            [u, v, w] = input().split()
            edges.append(Edge(u, v, int(w)))
        graph = Graph(edges)
        for j in range(int(q)):
            q = input()
            distance = graph.dijkstra(s, q)
            if distance == 0 and s != q:
                print("Impossible")
            else:
                print(distance)
        print("\n")

0 个答案:

没有答案