牛客 NC99 树的直径

描述
给定一棵树,求出这棵树的直径,即树上最远两点的距离。
包含n个结点,n-1条边的连通图称为树。
示例1的树如下图所示。其中4到5之间的路径最长,是树的直径,距离为5+2+4=11
在这里插入图片描述

示例1

输入:
6,[[0,1],[1,5],[1,2],[2,3],[2,4]],[3,4,2,1,5]
返回值:
11

思路:

  1. 定义
    简单路径:路径上的所有点至多只访问了一次。
    树的直径:树的最长的简单路径。
  2. 算法
    (1)两次BFS/DFS:先任选一个起点,BFS/DFS找到最长路的终点,再从终点进行第二次BFS/DFS找到最长路即为树的直径。
    原理:设起点为u,第一次BFS/DFS找到的终点v一定是树的直径的一个端点。
    证明:1)如果u是直径上的点,则v就是直径的终点(因为如果v不是的话,则必定存在另一个点w使得u到w的距离更长,则与BFS/DFS找到了v矛盾。
    2) 如果u不是直径上的点,则u到v必然与树的直径相交(反证),那么交点到v必然就是直径的后半段了,所以v一定是直径的一个端点,所以从v进行BFS/DFS得到的一定是直径长度。

code:

# class Interval:
#     def __init__(self, a=0, b=0):
#         self.start = a
#         self.end = b

#
# 树的直径
# @param n int整型 树的节点个数
# @param Tree_edge Interval类一维数组 树的边
# @param Edge_value int整型一维数组 边的权值
# @return int整型
#
class Solution:
    maxn = 0
    u = v = 0
    
    def dfs(self, gragh, current, pre, distance):
        """

        :param current: 当前节点
        :param pre: 上一个节点
        :param distance: 最初节点到当前节点的距离
        :return:
        """
        if len(gragh[current]) == 1 and pre in gragh[current]:
            if self.maxn < distance:
                self.maxn = distance
                self.v = current
            return
        for key in gragh[current]:
            if key != pre:
                self.dfs(gragh, key, current, distance + gragh[current][key])
                

    def solve(self, n, Tree_edge , Edge_value ):
        # 构建图
        gragh = {}
        for i in range(len(Edge_value)):
            e = Tree_edge[i]
            if e.start not in gragh:
                gragh[e.start] = {}
            gragh[e.start][e.end] = Edge_value[i]
            if e.end not in gragh:
                gragh[e.end] = {}
            gragh[e.end][e.start] = Edge_value[i]
        print(gragh)
        self.dfs(gragh, self.u, -1, 0)  # 第一次搜索,从节点0(u)开始,找到简单路径最远的点v,即树的直径的第一个端点
        self.dfs(gragh, self.v, -1, 0)  # 第二次搜索,从节点v(第一个端点)开始,找到简单路径最远的点,即树的直径的另一个端点
        return self.maxn
        
        
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值