树hackerrank解决方案错误的故事

时间:2017-06-30 07:09:10

标签: python algorithm graph tree dfs

hackerrank中的

Found this problem并且没有通过一些测试用例。

有一天,鲍勃在一张纸上画了一棵树,上面有 n 个节点和 n-1 边。他很快发现节点的父节点取决于树的根。以下图片显示了一个示例:

enter image description here

了解这一事实,鲍勃发明了一款激动人心的新游戏,并决定与爱丽丝一起玩。游戏规则如下所述:

  1. Bob选择一个随机节点作为树的根,并保持所选节点的身份与Alice保密。每个节点被选为根的概率相等。

  2. Alice然后列出了 g 猜测,其中每个猜测的格式为 uv ,这意味着Alice猜测 gn(v)=你是真的。它保证了树中存在连接 u v 的无向边。 对于每个正确的猜测,Alice获得一分。如果她获得至少 k 分(即,至少 k 她的猜测是真的),Alice会赢得比赛。

  3. Alice和Bob玩 q 游戏。给定树,Alice的猜测,以及每个游戏的 k 的值,找到Alice将赢得游戏的概率并将其作为格式中的缩小部分打印在新行上p / q

    解决方案: 有一棵树,边上标有箭头。对于树中的每个顶点,您必须计算有多少箭头指向它。对于一个固定顶点,这可以通过一个DFS完成。在DFS期间以与其自身相反的方向遍历的每个箭头都会增加1.如果您知道顶点v的答案,则可以在O(1)中计算与v相邻的顶点u的答案。  它与v几乎相同,但是如果有箭头u-> v或v-> u,它们的贡献是相反的。现在你可以通过移动到相邻的方式使顶点在整个图形上爬行第二个DFS中的顶点。

    问题:无法通过所有测试用例。我对代码进行了完整性测试并发现没有问题,但我没有得到任何线索,为什么这不适用于hackerrank平台。

    import sys
    
    def gcd(a, b):
        if not b:
            return a
        return gcd(b, a%b)
    
    def dfs1(m, guess, root, seen):
        '''keep 1 node as root and calculate how many arrows are pointing towards it'''
        count = 0
        for i in m[root]:
            if seen[i][root] != 1 and seen[root][i] != 1:
                seen[i][root] = 1
                seen[root][i] = 1
                count += (1 if guess[root][i] == 1 else 0) + dfs1(m, guess, i, seen)
        return count
    
    def dfs2(m, guess, root, seen, cost, k):
        '''now make every node as root and calculate how many nodes
           are pointed towards it; If u is the root node for which
           dfs1 calculated n (number of arrows pointed towards the root)
           then for v (adjacent node of u), it would be n-1 as v is the
           made the parent now in this step (only if there is a guess, if
           there is no guess then it would be not changed)'''
        win = cost >= k
        for i in m[root]:
            if seen[i][root] != 1 and seen[root][i] != 1:
                seen[i][root] = 1
                seen[root][i] = 1
                win += dfs2(m, guess, i, seen, cost - (1 if guess[root][i] == 1 else -guess[i][root]), k)
        return win
    
    
    q = int(raw_input().strip())
    for a0 in xrange(q):
        n = int(raw_input().strip())
        m = {}
        guess = [[0 for i in range(n+1)] for i in range(n+1)]
        seen = [[0 for i in range(n+1)] for i in range(n+1)]
        for a1 in xrange(n-1):
            u,v = raw_input().strip().split(' ')
            u,v = [int(u),int(v)]
            if u not in m:
                m[u] = []
            m[u].append(v)
            if v not in m:
                m[v] = []
            m[v].append(u)
        g,k = raw_input().strip().split(' ')
        g,k = [int(g),int(k)]
        for a1 in xrange(g):
            u,v = raw_input().strip().split(' ')
            u,v = [int(u),int(v)]
            guess[u][v] = 1
        cost = dfs1(m, guess, 1, seen)
        seen = [[0 for i in range(n+1)] for i in range(n+1)]
        win = dfs2(m, guess, 1, seen, cost, k)
        g = gcd(win, n)
        print("{0}/{1}".format(win/g, n/g))
    

1 个答案:

答案 0 :(得分:0)

一种可能性是代码是正确的,但是你得到了堆栈溢出。

可能有100,000个节点,如果它们全部连接成一行,则深度优先搜索递归将失败。

如果这是真的,那么将DFS代码从递归转换为迭代公式(通过在数组中保留一堆东西)应该会有所帮助。

另一种可能性是可能存在诸如1,2和猜测之类的猜测,例如2,1。在这种情况下,我不确定分数更新代码是否有效:

win += dfs2(m, guess, i, seen, cost - (1 if guess[root][i] == 1 else -guess[i][root]), k)

也许这会更好:

win += dfs2(m, guess, i, seen, cost - guess[root][i] + guess[i][root], k)