本文共 2627 字,大约阅读时间需要 8 分钟。
为了找到所有人走到同一地点所需的最少时间,我们可以将问题转化为在树中找到一个中心点,使得所有指定点到该中心点的距离之和最小。以下是详细的解决方案:
给定一个包含n个点的树结构,其中k个点被标记为有人。每次沿边移动需要1分钟,目标是找到一个点,使得所有k个人走到该点所需的时间最少。
树的中心点:树的中心点是指树中任意两个叶子节点之间的最短路径的中点。这个点通常是树的直径端点之间的中点,能够使所有节点到它的距离之和最小。
找到树的直径:
确定中心点:树的中心点通常是直径的中点,或者沿着直径中间的节点。这个点到所有节点的距离之和最小。
计算总时间:计算所有k个指定点到中心点的距离之和,即为所需的最少时间。
import sysfrom collections import dequedef find_center_tree(n, edges, k_points): # 构建树的邻接表 tree = [[] for _ in range(n+1)] for u, v in edges: tree[u].append(v) tree[v].append(u) # 找到直径的两个端点u和v def bfs(start): visited = [False] * (n + 1) distance = [0] * (n + 1) q = deque() q.append(start) visited[start] = True max_dist = 0 far_node = start while q: current = q.popleft() for neighbor in tree[current]: if not visited[neighbor]: visited[neighbor] = True distance[neighbor] = distance[current] + 1 q.append(neighbor) if distance[neighbor] > max_dist: max_dist = distance[neighbor] far_node = neighbor return far_node, max_dist u, _ = bfs(1) v, _ = bfs(u) # 确定中心点 # 假设中心点是u和v的中点,或者取决于树的结构 # 这里假设取u和v的中点 center = (u + v) // 2 # 计算k个点到中心点的距离之和 total_time = 0 for node in k_points: if node == center: continue # 计算从node到center的距离 dist = 0 current = node while current != center and current != 0: dist += 1 current = tree[current][0] if tree[current] else 0 total_time += dist return total_timedef main(): input = sys.stdin.read().split() ptr = 0 n = int(input[ptr]) ptr += 1 m = int(input[ptr]) ptr += 1 edges = [] for _ in range(m): u = int(input[ptr]) ptr += 1 v = int(input[ptr]) ptr += 1 edges.append((u, v)) k = int(input[ptr]) ptr += 1 k_points = [] for _ in range(k): node = int(input[ptr]) ptr += 1 k_points.append(node) total_time = find_center_tree(n, edges, k_points) print(total_time)if __name__ == "__main__": main()
构建邻接表:读取输入数据并构建树的邻接表,用于后续的BFS遍历。
BFS遍历:两次BFS遍历,首先从随机节点出发,找到最远的节点u。然后从u出发,找到最远的节点v,这两个节点确定了树的直径。
确定中心点:中心点通常是直径的中点,或者沿着直径中间的节点。
计算总时间:从每个指定点到中心点的距离之和即为所需的最少时间。
通过上述方法,我们能够高效地找到所有人走到同一地点所需的最少时间。该方法的时间复杂度主要取决于BFS遍历的效率,通常在O(n)时间内完成,适用于大规模树结构。
转载地址:http://zluv.baihongyu.com/