【问题标题】:Programming a BFS - Shortest Path - in Python用 Python 编写 BFS - 最短路径
【发布时间】:2016-02-03 21:28:20
【问题描述】:

我是 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 个边的测试用例,我的答案对于许多节点来说太高了。

我们将不胜感激。

提前致谢,

【问题讨论】:

  • 它到底是怎么失败的?超出语法、运行时、时间限制?
  • 为什么测试用例的大小会妨碍调试?
  • 不看测试用例怎么知道问题出在哪里?
  • 我得到的答案是错误的。某处一定有逻辑错误,但我不知道它在哪里。我尝试使用循环创建较小的图,即访问每个节点的根,但所有这些似乎都可以正常工作。
  • 很少有人会阅读您所有的问题和所有代码。如果您想增加获得答案的机会,我建议您添加一个简单的示例来演示该问题

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


【解决方案1】:

编辑:我发现的原始“问题”状况是错误的,现在更正

counterlevels 的设置方式有问题。

假设R 是根节点,ABC 是其他节点,那么您的代码当前遇到问题时

R <-> A
A <-> B
R <-> B
B <-> C

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

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

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

这会改变您的输出,使得 5 节点的距离变为 18 而不是 12。

认为解决方案是将levels[v] = counter 放在条件块内,即

for v in nbrsList:
    if v not in fringe and v not in marked:
        levels[v] = counter
        distances[v] = 6*counter
        fringe += [v]

【讨论】:

  • 太棒了。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-18
  • 1970-01-01
相关资源
最近更新 更多