编程BFS - 最短路径 - 在Python中

时间:2016-02-03 21:28:20

标签: python graph shortest-path breadth-first-search

我是Python的新手,我正在尝试编写一个BFS来返回图表的最短路径。每条边的长度为6。

注意:这是HackerRank的一个问题。

我的代码适用于6个测试用例中的3个,但是其他3个失败。我不知道为什么并且因为测试用例太大而无法进行调试。

我的代码是:

# Enter your code here. Read input from STDIN. Print output to STDOUT    

def shortestPath():
    testCases = int(raw_input())

    for a in range(testCases):
        nodes,edges = raw_input().strip().split(' ')
        numNodes,edges = [int(nodes), int(edges)]

        edgeList = []

        # input data
        for b in range(edges):
            a,b = raw_input().strip().split(' ')
            a,b = [int(a), int(b)]
            edgeList += [[a,b]]
        root = int(raw_input())

        marked = [] # what I've checked
        fringe = [root] # things to check
        distances = {} # what to return
        levels = {root: 0} # the level of each element
        counter = 1

        # do the BFS
        while fringe != []:
            node = fringe[0]
            fringe.remove(node)
            marked += [node]
            if counter > levels[node] + 1:
                counter = levels[node] + 1
            nbrsList = Nbrs(node, edgeList)
            for v in nbrsList:
                levels[v] = counter
                if v not in fringe and v not in marked:
                    distances[v] = 6*counter
                    fringe += [v]
            counter += 1

        listOfNodes = nodeList(edgeList, numNodes)

        for node in listOfNodes:
            if node != root:
                if node in distances:
                    print distances[node],
                else:
                    print -1,  
        print ""
    print ""

def nodeList(edges, numNodes):
    nodes = []
    for edge in edges:
        for element in edge:
            if element not in nodes:
                nodes += [element]
    nodes.sort()

    for x in range(1,numNodes+1):
        if x not in nodes:
            nodes += [x]
    nodes.sort()
    return nodes


def Nbrs(node, edges):
    tempList = []
    for edge in edges:
        if node in edge:
            for element in edge:
                if element != node:
                    tempList += [element]
    return tempList

例如,我使用了以下测试用例:

  

1
  5 8
  1 2
  3 4
  4 5
  5 2
  2 4
  2 3
  1 3
  1 4
  3

其中第一行是测试用例的数量,第二行是节点数,边数,剩下的n-1行是边,最后一行是根。

这非常有效。我尝试将其改为我能想到的一切,似乎有效。然而,有了70个节点和1988年边缘的网站测试用例,我的答案对于许多节点来说太高了。

非常感谢任何和所有帮助。

提前致谢,

1 个答案:

答案 0 :(得分:1)

编辑:原始问题'我发现的情况有误,现在更正了

您设置levelsR的方式存在问题。

假设A是根节点,BCR <-> A A <-> B R <-> B B <-> C 是其他节点,则您的代码当前存在问题

5

并按照该顺序评估关系。它认为从R到C的最短路径是R - > A - &gt; B - &gt; C而不是R - > B - &gt;下进行。

您可以通过重新排序示例输入集来重现此问题:

  

1
  5 8
  1 2
  1 3#移动了这个和
  1 4#这个了   3 4
  4 5
  5 2
  2 4
  2 3
  3

这会改变您的输出,使levels[v] = counter节点的距离变为18而不是12。

认为解决方案是将for v in nbrsList: if v not in fringe and v not in marked: levels[v] = counter distances[v] = 6*counter fringe += [v] 放入条件块中,即

{{1}}