题解 | #我们的距离#

我们的距离

http://www.nowcoder.com/practice/14de961632784129a17a512c4a214d4a

方法零:用边的信息构造邻接矩阵,用floyd算法求节点间的最短距离,求和输出。这个方法用python实现超时,floyd算法对于边相对稀疏的树效率不高。(C++这么做可以通过,代码略)
方法一:遍历所有边,更新连通分量(Connected Component)和每个连通分量内的节点两两之间距离,最后求和得到答案输出

# class Point:
#     def __init__(self, a=0, b=0):
#         self.x = a
#         self.y = b
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param n int整型 点的数量
# @param edge Point类一维数组 Point.x , Point.y 边所连接的两个点
# @return long长整型一维数组
#
class Solution:
    def solve(self , n , edge ):
        # write code here
        ran=range(n)
        dis=[[n]*n for i in ran]
        cur=0
        cc=[0]*n# Connected Component
        ccr=[]
        for i in ran:
            dis[i][i]=0
        for e in edge:
            x,y=e.x,e.y
            if cc[x-1]==0:# x not in cc
                if cc[y-1]==0:# y not in cc
                    cur+=1
                    ccr.append([x,y])
                    cc[x-1],cc[y-1]=cur,cur
                    dis[x-1][y-1]=1
                    dis[y-1][x-1]=1
                else:# y in cc
                    for a in ccr[cc[y-1]-1]:
                        dis[x-1][a-1]=dis[y-1][a-1]+1
                        dis[a-1][x-1]=dis[a-1][y-1]+1
                    cc[x-1]=cc[y-1]# connect x to cc of y
                    ccr[cc[y-1]-1].append(x)
            else:# x in cc
                if cc[y-1]==0:# y not in cc
                    for a in ccr[cc[x-1]-1]:
                        dis[y-1][a-1]=dis[x-1][a-1]+1
                        dis[a-1][y-1]=dis[a-1][x-1]+1
                    cc[y-1]=cc[x-1]# connect y to cc of x
                    ccr[cc[x-1]-1].append(y)
                else:# y in cc
                    # if x==y then we find a loop, but tree doesn't have loops
                    # so x=!y always true, merge cc
                    for a in ccr[cc[x-1]-1]:
                        for b in ccr[cc[y-1]-1]:
                            dis[a-1][b-1]=dis[a-1][x-1]+1+dis[y-1][b-1]
                            dis[b-1][a-1]=dis[b-1][y-1]+1+dis[x-1][a-1]
                    tmp=cc[x-1]
                    for b in ccr[cc[y-1]-1]:
                        cc[b-1]=tmp
                        ccr[tmp-1].append(b)
        f=[]
        for i in ran:
            f.append(sum(dis[i]))
        return f

方法二:DFS递归,保存中间值,参考这篇文章:hdu6446(dp+树上任意两点的最短距离)https://blog.csdn.net/rain722/article/details/75633721

# class Point:
#     def __init__(self, a=0, b=0):
#         self.x = a
#         self.y = b
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param n int整型 点的数量
# @param edge Point类一维数组 Point.x , Point.y 边所连接的两个点
# @return long长整型一维数组
#

class Solution:
    subtree=[]
    cnt=[]
    ans=[]
    def solve(self, n, edge):
        # write code here
        ran = range(n)
        Solution.subtree = [[]*n for i in ran]
        Solution.cnt = [[0]*n for i in ran]
        Solution.ans = [[0]*n for i in ran]
        for e in edge:
            Solution.subtree[e.x-1].append(e.y-1)
            Solution.subtree[e.y-1].append(e.x-1)
        for i in ran:
            self.dfs(i, i)
        return [Solution.ans[i][i] for i in ran]

    def dfs(self, cur, father):
        if Solution.cnt[cur][father] == 0:
            if cur!=father:
                Solution.cnt[cur][father] = 1
            for son in Solution.subtree[cur]:
                if son == father:
                    continue
                self.dfs(son, cur)
                Solution.cnt[cur][father] += Solution.cnt[son][cur]
                Solution.ans[cur][father] += Solution.ans[son][cur]
            if cur!=father:
                Solution.ans[cur][father] += Solution.cnt[cur][father]
全部评论

相关推荐

牛客5655:其他公司的面试(事)吗
点赞 评论 收藏
分享
头像
11-21 11:39
四川大学 Java
是红鸢啊:忘了还没结束,还有字节的5k 违约金
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务