트리의 지름
https://www.acmicpc.net/problem/1167
https://www.acmicpc.net/problem/1967
트리에 대해서 안다고 하지만 막상 문제를 풀어보면 모르는게 맞다. 문제에서 정의하는 트리의 지름이란 하나의 정점에서 다른 정점까지의 거리를 트리의 지름이라고 칭하고 해당 지름 중 가장 큰 지름의 값을 구하는 것이 문제였다.
항상 문제는 어렵기 때문에 고민을 어느정도 하고 답을 살펴본다. dfs 에 대한 문제였고 이 문제가 말하는 것은 해당 지름이 루트를 거치냐 혹은 거치지 않냐 두 가지로 나뉠 수가 있었다.
예를 들어 트리가 하나 주어졌다고 상상하자.
그럼 트리에는 루트가 있고 루트 하위에는 서브트리가 여러 개 존재할 것이다. 그럼 트리의 지름은 서브트리를 고려했을때 두 가지 경우로 생각할 수 있다.
1) 서로 다른 서브트리에서 두 개의 정점을 추출하고 서로 간의 거리를 구한 경우
2) 하나의 서브트리 내에서 두 개의 정점을 추출하고 서로 간의 거리를 구한 경우
1의 경우에는 루트를 거리를 구하는 와중에 루트를 거치지만
2의 경우에는 거치지 않는다.
결국 하나의 정점의 하위 서브트리에서의 정점간의 거리를 구하는 것이 주 핵심이고, 정점의 거리는 결국 두 개로 표현할 수 있다. 루트에서 왼쪽 정점으로의 거리1, 루트에서 오른쪽 정점으로의 거리2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | import java.io.*; import java.math.BigInteger; import java.util.*; public class Main { static InputStreamReader isr; static BufferedReader br; static OutputStreamWriter osw; static BufferedWriter bw; static StringTokenizer st; static ArrayList<ArrayList<Vertex>> list = new ArrayList<ArrayList<Vertex>>(); static boolean visited[] = null; static int d = 0; public static void main(String[] args) throws IOException { isr = new InputStreamReader(System.in); br = new BufferedReader(isr); osw = new OutputStreamWriter(System.out); bw = new BufferedWriter(osw); int V = Integer.parseInt(br.readLine()); visited = new boolean[V+1]; for(int i = 0; i <= V; i++) list.add(new ArrayList<Vertex>()); for(int i = 0; i < V; i++){ st = new StringTokenizer(br.readLine()); int sv = Integer.parseInt(st.nextToken()); while(st.hasMoreTokens()){ int ev = Integer.parseInt(st.nextToken()); if(ev == -1) break; int cost = Integer.parseInt(st.nextToken()); list.get(sv).add(new Vertex(ev, cost)); } }// input visited[1] = true; dfs(1); bw.write(d + "\n"); bw.close(); br.close(); } // (1) 루트로부터 가장 멀리 떨어진 subTree 각각 두 개의 거리 // (2) 같은 subTree 내에서의 두 개의 거리 // sv와 가장 먼 정점의 dist 획득 private static int dfs(int sv){ int max1 = 0; // 가장 먼 int max2 = 0; // 두번째로 먼 for(int eIndex = 0; eIndex < list.get(sv).size(); eIndex++){ Vertex vertex = list.get(sv).get(eIndex); // 방문 if(visited[vertex.ev]) continue; visited[vertex.ev] = true; int dist = dfs(vertex.ev) + vertex.cost; // dist 가 제일 크면 if(dist > max1){ max2 = max1; max1 = dist; } // dist 가 두번째로 크면 else if(dist > max2){ max2 = dist; } } // 루트로부터 떨어진 두 개의 간선 합 => d d = Math.max(d, max1+max2); return max1; } } class Vertex{ int ev; int cost; public Vertex(int ev, int cost){ this.ev = ev; this.cost = cost; } } | cs |
'Problem Solving & Algorithm > BOJ ' 카테고리의 다른 글
20180826 8월 BOJ 풀이 : 트리의 순회 (0) | 2018.08.26 |
---|---|
20180825 8월 BOJ 풀이 : 트리의 높이와 너비 (0) | 2018.08.25 |
20180707 7월 BOJ 문제풀이 (0) | 2018.07.08 |
20180616 백준 동전문제들. (0) | 2018.06.16 |
20180603 6월 BOJ 풀이 : 더럽게 안 풀린 것들 (0) | 2018.06.03 |