트리의 지름
2 초 | 256 MB | 24238 | 8805 | 6307 | 34.246% |
문제
트리의 지름이란, 트리에서 임의의 두 점 사이의 거리 중 가장 긴 것을 말한다. 트리의 지름을 구하는 프로그램을 작성하시오.
입력
트리가 입력으로 주어진다. 먼저 첫 번째 줄에서는 트리의 정점의 개수 V가 주어지고 (2 ≤ V ≤ 100,000)둘째 줄부터 V개의 줄에 걸쳐 간선의 정보가 다음과 같이 주어진다. 정점 번호는 1부터 V까지 매겨져 있다.
먼저 정점 번호가 주어지고, 이어서 연결된 간선의 정보를 의미하는 정수가 두 개씩 주어지는데, 하나는 정점번호, 다른 하나는 그 정점까지의 거리이다. 예를 들어 네 번째 줄의 경우 정점 3은 정점 1과 거리가 2인 간선으로 연결되어 있고, 정점 4와는 거리가 3인 간선으로 연결되어 있는 것을 보여준다. 각 줄의 마지막에는 -1이 입력으로 주어진다. 주어지는 거리는 모두 10,000 이하의 자연수이다.
출력
첫째 줄에 트리의 지름을 출력한다.
풀이
이전 백준 1967번을 통해 트리의 지름에 대한 증명을 학습했기 때문에 쉽게 풀 수 있었습니다.
1) 루트로 부터 가장 먼 노드를 구한다
2) 그 노드에서 가장 먼 노드와의 가중치가 곧 트리의 지름이다
트리의 연결관계 저장 방식: ArrayList + 객체
연결관계는 배열을 사용하면 메모리 낭비와 중복 탐색이 발생하므로 ArrayList 안에 저장하며, 가중치까지 같이 저장해야하므로 객체 안에 연결된 노드 번호와 가중치를 저장합니다.
static class Node{
int num, weight;
Node(int num, int weight){
this.num = num;
this.weight =weight;
}
}
입력값 받기
이전과 다른점은 입력 방식 뿐입니다. 하지만 트리의 경우 개념 조건에 따라 모두 연결되어있기 때문에 각 정점에 대해 간선이 최소 하나가 존재합니다.
for(int i=1;i<=node;i++) {
st = new StringTokenizer(br.readLine()); // 토크나이저로 받아주고
int num = Integer.parseInt(st.nextToken()); // 맨 앞 숫자를 가져옵니다
int v = (st.countTokens()-1)/2; // 나머지 토큰의 개수는 -1을 포함해 홀수개입니다
while(v-->0) { //트리의 연결관계를 넣어줍니다
tree[num].add(new Node(Integer.parseInt(st.nextToken()),Integer.parseInt(st.nextToken())));
}
}
탐색법: DFS + 방문체크
dfs와 방문체크를 같이 적용해야하며 가중치의 최대값이 갱신될 때 그 노드의 번호를 가져와야 합니다(트리 지름 증명을 활용).
static void dfs(int n, int sum) {
check[n] = true;
if(MAX<sum) { //가중치의 최대값이 갱신될 때 노드 번호를 가져옵니다
MAX = sum;
idx = n;
}
//연결된 노드 중 방문하지 않은 곳을 가중치를 더하고 들어갑니다
for(int i=0;i<tree[n].size();i++) {
if(!check[tree[n].get(i).num]) {
dfs(tree[n].get(i).num,sum+tree[n].get(i).weight);
}
}
}
전체 풀이
import java.io.*;
import java.util.*;
public class Main {
static int MAX,idx;
static ArrayList<Node>[] tree;
static boolean[] check;
static class Node{
int num, weight;
Node(int num, int weight){
this.num = num;
this.weight =weight;
}
}
static void dfs(int n, int sum) {
check[n] = true;
if(MAX<sum) {
MAX = sum;
idx = n;
}
for(int i=0;i<tree[n].size();i++) {
if(!check[tree[n].get(i).num]) {
dfs(tree[n].get(i).num,sum+tree[n].get(i).weight);
}
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
int node = Integer.parseInt(br.readLine());
tree = new ArrayList[node+1];
check = new boolean[node+1];
for(int i=0; i<node+1;i++) {
tree[i] = new ArrayList<>();
}
for(int i=1;i<=node;i++) {
st = new StringTokenizer(br.readLine());
int num = Integer.parseInt(st.nextToken());
int v = (st.countTokens()-1)/2;
while(v-->0) {
tree[num].add(new Node(Integer.parseInt(st.nextToken()),Integer.parseInt(st.nextToken())));
}
}
dfs(1,0);
check = new boolean[node+1];
dfs(idx,0);
System.out.println(MAX);
}}
'Study > Baekjoon' 카테고리의 다른 글
[Python]Baekjoon2628: 종이자르기 (0) | 2022.01.27 |
---|---|
[Python] Baekjoon2669: 직사각형 네개의 합집합의 면적 구하기 (0) | 2022.01.26 |
[Java] Baekjoon1967: 트리의 지름 / 오답의 이유 모두 분석 (0) | 2022.01.23 |
[Python]Baekjoon9996: 한국이 그리울 땐 서버에 접속하지 (0) | 2022.01.23 |
[Python] Baekjoon1051: 숫자 정사각형 (0) | 2022.01.22 |