这题我一开始想法是暴搜。从每个边缘结点出发,都进行一次bfs,找出最大步数。但是肯定过不了全部用例,暴力搜索只拿了70。后来看别人的文章,才知道是考树的直径。
树的直径(最长路) 的详细证明
具体结论是:
从任意一点出发搜出最远的点,然后在从这个最远点开始搜,就可以搜到另一个最长路的端点,即用两遍广搜就可以找出树的最长路。
我的理解:
最长路的结点肯定在边缘嘛,但是怎么确定哪些边缘点能组成最长路呢,照以上结论,第一遍bfs,无论从哪点出发,找出的最远点(一个或多个),肯定能组成最长路的其中一个点。然后再从此点(任意一个最远点)出发找出另一个最远点,组成最长路。
python代码(100)
from queue import Queue
def bfs(start, graph):
"""返回最后一个结点和最大步数"""
lastNode = None # 最后一个结点
maxStep = 0 # 最大步数
queue = Queue()
queue.put([start, 0])
vis = [False for _ in range(len(graph))]
vis[start] = True
while not queue.empty():
node, step = queue.get()
lastNode = node
maxStep = step
for e in graph[node]:
if not vis[e]:
queue.put([e, step + 1])
vis[e] = True
return lastNode, maxStep
n, m = map(int, input().split())
# 建立邻接表
# 前n个是交换机,后m个是终端
changes = [int(v) for v in input().split()]
ends = [int(v) for v in input().split()]
graph = [[] for _ in range(n + m)]
for i in range(1, n):
graph[i].append(changes[i - 1] - 1)
graph[changes[i - 1] - 1].append(i)
for i in range(m):
graph[n + i].append(ends[i] - 1)
graph[ends[i] - 1].append(n + i)
# 一开始从任意一点出发bfs,找出最远点
longnode = bfs(0, graph)[0]
# 再从这个最远点出发bfs,找全局最远路线
maxStep = bfs(longnode, graph)[1]
print(maxStep)