【Lintcode】1469. Longest Path On The Tree

tech2025-05-03  6

题目地址:

https://www.lintcode.com/problem/longest-path-on-the-tree/description

给定一棵有 n n n个顶点的无向带权图,其具有树性质。求其直径。

思路是,先用BFS从任意一个点 v v v开始对图进行遍历,找到离 v v v最远的那个顶点 u u u,然后再从 u u u开始BFS,找到离 u u u最远的顶点,这个距离就是直径。之所以不用DFS是因为容易爆栈。

算法正确性证明: 对图的顶点个数进行归纳。如果图只有 1 1 1或者 2 2 2个顶点,算法正确。如果有 n n n个顶点,假设第一次BFS的时候是从 v v v开始遍历的,如果有直径通过 v v v,那么算法显然成立;如果所有直径都不通过 v v v,那么其必在去掉 v v v后产生的若干个连通分量的其中一个里。设这些连通分量的“入口”分别是 x 1 , . . . , x r x_1,...,x_r x1,...,xr,由归纳假设,这些连通分量每一个的直径都存在一个点 y 1 , . . . , y r y_1,...,y_r y1,...,yr使得它们都是在各自连通分量里离 x i x_i xi最远的点。而这些点必然有其中一个是离 v v v最远的。所以直径的一个端点必然能被算法搜出来。所以算法正确。

代码如下:

import java.util.*; public class Solution { /** * @param n: The number of nodes * @param starts: One point of the edge * @param ends: Another point of the edge * @param lens: The length of the edge * @return: Return the length of longest path on the tree. */ public int longestPath(int n, int[] starts, int[] ends, int[] lens) { // Write your code here Map<Integer, List<int[]>> graph = buildGraph(starts, ends, lens); int[] res = bfs(0, graph, n); return bfs(res[0], graph, n)[1]; } // 从start顶点开始bfs,返回一个长度为2的数组res, // res[0]表示离start最远的点的编号,res[1]表示其离start的距离 private int[] bfs(int start, Map<Integer, List<int[]>> graph, int n) { int[] res = {0, 0}; boolean[] visited = new boolean[n]; visited[start] = true; // 由于是树,所以可以直接用普通的队列而不是优先队列,因为树的两个顶点的路径是唯一的 Queue<int[]> queue = new LinkedList<>(); queue.offer(new int[]{start, 0}); while (!queue.isEmpty()) { int[] cur = queue.poll(); for (int[] next : graph.get(cur[0])) { if (visited[next[0]]) { continue; } visited[next[0]] = true; if (cur[1] + next[1] > res[1]) { res[0] = next[0]; res[1] = cur[1] + next[1]; } queue.offer(new int[]{next[0], cur[1] + next[1]}); } } return res; } private Map<Integer, List<int[]>> buildGraph(int[] starts, int[] ends, int[] lens) { Map<Integer, List<int[]>> graph = new HashMap<>(); for (int i = 0; i < starts.length; i++) { graph.computeIfAbsent(starts[i], k -> new ArrayList<>()).add(new int[]{ends[i], lens[i]}); graph.computeIfAbsent(ends[i], k -> new ArrayList<>()).add(new int[]{starts[i], lens[i]}); } return graph; } }

时空复杂度 O ( n ) O(n) O(n)

最新回复(0)