算法一:经典做法——两遍dfs
任选一点找到距离该点最远的点u
在找到距离u最远的点v则u-v路径就是一条直径
import java.util.*;
class Main{
private static int ans, maxv, maxd;
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
createAdj(n);
for(int i = 1; i < n; i++){
int a = sc.nextInt();
int b = sc.nextInt();
int c = sc.nextInt();
add(a, b, c);
add(b, a, c);
}
dfs(1, -1, 0);
dfs(maxv, -1, 0);
System.out.println(maxd);
}
private static void dfs(int u, int fa, int d){
for(int i = h[u]; i != -1; i = ne[i]){
int j = e[i];
if(j == fa) continue;
if(d + w[i] > maxd){
maxd = d + w[i];
maxv = j;
}
dfs(j, u, d + w[i]);
}
}
private static int[] h, e, w, ne;
private static int idx;
private static void createAdj(int n){
h = new int[n+1];
e = new int[n*2];
w = new int[n*2];
ne = new int[n*2];
Arrays.fill(h, -1);
idx = 0;
}
private static void add(int a, int b, int c){
e[idx] = b;
w[idx] = c;
ne[idx] = h[a];
h[a] = idx++;
}
}
算法二:树形DP——所有挂在节点u中直径的集合
import java.util.*;
class Main{
private static int ans;
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
createAdj(n);
for(int i = 1; i < n; i++){
int a = sc.nextInt();
int b = sc.nextInt();
int c = sc.nextInt();
add(a, b, c);
add(b, a, c);
}
dfs(1, -1);
System.out.println(ans);
}
private static int dfs(int u, int fa){
int max1 = 0, max2 = 0; //表示节点u子节点中深度最长的两条边
for(int i = h[u]; i != -1; i = ne[i]){
int j = e[i];
if(j == fa) continue;
int d = dfs(j, u) + w[i];
if(d > max1){
max2 = max1; max1 = d;
}else{
if(d > max2) max2 = d;
}
}
ans = Math.max(ans, max1 + max2);
return max1;
}
private static int[] h, e, w, ne;
private static int idx;
private static void createAdj(int n){
h = new int[n+1];
e = new int[n*2];
w = new int[n*2];
ne = new int[n*2];
Arrays.fill(h, -1);
idx = 0;
}
private static void add(int a, int b, int c){
e[idx] = b;
w[idx] = c;
ne[idx] = h[a];
h[a] = idx++;
}
}