描述
给定一棵树,求出这棵树的直径,即树上最远两点的距离。
包含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)两次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