트리가 주어졌을 때, 트리의 지름(diameter)—서로 가장 먼 두 노드 간의 거리—를 구하는 문제를 풀면서 겪은 시행착오와 최종 해법을 정리했습니다.
리프 노드 수집
각 리프마다 BFS
// (생략) addLeafNodes(), inputSetting() 등...
for (int leaf : leafNodes) {
findByBfs(leaf);
}
❗️ 문제점
이 방식은 두 번의 그래프 순회(DFS 또는 BFS)만에 (O(N))에 해결할 수 있습니다.
depth + weight
를 전달하기 좋은 DFS를 선택했습니다.import java.io.*;
import java.util.*;
public class Main {
static int N;
static List<List<int[]>> adj = new ArrayList<>();
static boolean[] visited;
static int farNode, maxDist;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
// 인접 리스트 초기화
for (int i = 0; i <= N; i++) adj.add(new ArrayList<>());
for (int i = 0; i < N - 1; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int p = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken());
int w = Integer.parseInt(st.nextToken());
adj.get(p).add(new int[]{c, w});
adj.get(c).add(new int[]{p, w});
}
visited = new boolean[N + 1];
farNode = 1; maxDist = 0;
// 1) 임의의 노드(1)에서 가장 먼 노드 u 찾기
dfs(1, 0);
// 2) u에서 다시 가장 먼 v 찾기
Arrays.fill(visited, false);
maxDist = 0;
dfs(farNode, 0);
// 지름 출력 🎯
System.out.println(maxDist);
}
static void dfs(int curr, int dist) {
visited[curr] = true;
if (dist > maxDist) {
maxDist = dist;
farNode = curr;
}
for (int[] edge : adj.get(curr)) {
int nxt = edge[0], w = edge[1];
if (!visited[nxt]) {
dfs(nxt, dist + w);
}
}
}
}
static int[] bfs(int start) {
boolean[] vis = new boolean[N + 1];
Queue<int[]> q = new ArrayDeque<>();
q.add(new int[]{start, 0});
vis[start] = true;
int far = start, maxD = 0;
while (!q.isEmpty()) {
int[] cur = q.poll();
int u = cur[0], d = cur[1];
if (d > maxD) {
maxD = d;
far = u;
}
for (int[] e : adj.get(u)) {
int v = e[0], w = e[1];
if (!vis[v]) {
vis[v] = true;
q.add(new int[]{v, d + w});
}
}
}
return new int[]{far, maxD};
}
bfs(1)
→ ([u, _]) bfs(u)
→ ([_, diameter])