Study/Algorithm
[백준 1167] 트리의 지름
pink_salt
2024. 8. 23. 02:17
728x90
[백준 1167] 트리의 지름
접근
트리의 지름
- 트리 내의 두 노드 사이의 가장 긴 경로이다.
문제 풀이
- 입력을 트리로 변환
인접 리스트에 Point클래스 (목적지 노드, 가중치) 자료형 사용해서 가중치 있는 그래프 표현. - DFS 를 통해서 1에서 가장 멀리 떨어진 노드 탐색
- 가장 멀리 떨어진 노드를 기준으로 다시 DFS를 진행해서 트리의 지름을 구함.
사용한 알고리즘
DFS
시간 복잡도
O(n)
- 막힌 부분.
- DFS를 통해서 가장 멀리 떨어진 노드를 탐색하는 것까지는 생각함.
- 그 이후에 어떻게 지름을 구하는지에 대해서 막혔다.
지름을 구하기 위해서 다시 DFS 탐색이 필요하다는 것까지 생각을 못했다.. ㅜㅜ
2-1. 모든 경로의 경우의 수를 탐색해서 지름을 구하는 것도 생각했는데 이때 노드가 많아질수록 모든 경로를 탐색하는데 드는 시간이 매우 커질 것으로 생각이 들어서 포기했다. - 트리의 특성을 다시 파악하고 지름을 구하는 방법을 찾아서 적용하였다.
트리의 특성
- 사이클이 없는 구조이다.
트리 내의 두 노드 사이의 경로는 유일하다. - 트리의 지름은 이중에서 가장 긴 경로이다.
- 한 정점에서 가장 먼 정점으로 가는 경로와 가장 먼 정점 사이의 경로는 항상 일부가 겹친다. (해당 내용은 아래 이유와 예시를 보면 도움이 된다.)
두번의 DFS로 트리를 구할 수 있는 이유
- A에서 B가 가장 먼 노드라면 A와 B의 거리는 해당 범위의 지름이 된다.
- 각 노드에서 제일 먼 노드까지의 거리를 구해보면 아래 예시와 같다.
- 이때 1에서 5까지가 가장 먼 거리이다. -> 지름
- 임의의 노드에서부터 최장 정점은 1 또는 5를 항상 포함하고 있다.
- 일단 임의의 노드로 시작점을 잡고 해당 노드에서의 가장 먼 노드를 찾고
- 가장 먼 노드를 기점으로 또 가장 먼 노드를 찾게 되어 해당 거리를 갱신하면 해당 트리에서의 지름을 구할 수 있다.
전체코드
import java.util.*;
import java.io.*;
public class Main {
static class Point {
int destination;
int weight;
public Point(int destination, int weight) {
this.destination = destination;
this.weight = weight;
}
}
static int V;
static List<Point>[] list;
static boolean[] visited;
static int maxDistance;
static int farthestNode;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
V = Integer.parseInt(br.readLine());
StringTokenizer st;
list = new ArrayList[V + 1];
for (int i = 1; i <= V; i++) {
list[i] = new ArrayList<>();
}
for (int i = 1; i <= V; i++) {
st = new StringTokenizer(br.readLine());
int node = Integer.parseInt(st.nextToken());
while (true) {
int destination = Integer.parseInt(st.nextToken());
if (destination == -1) break;
int weight = Integer.parseInt(st.nextToken());
list[node].add(new Point(destination, weight));
}
}
visited = new boolean[V + 1];
dfs(1, 0);
System.out.println(maxDistance);
}
static void dfs(int node, int distance) {
visited[node] = true;
if (distance > maxDistance) {
maxDistance = distance;
farthestNode = node;
}
for (Point point : list[node]) {
if (!visited[point.destination]) {
dfs(point.destination, distance + point.weight);
}
}
}
}
728x90
반응형