[백준] 12912번 - 트리 수정 (Gold 1)
업데이트:
문제 링크
문제 설명
트리에서 간선 하나를 제거하고 제거한 간선의 가중치와 같은 가중치를 가지는 간선을 하나 추가하여 새로운 트리를 만드려고 한다. 가능한 새로운 트리의 지름의 최댓값을 구하시오.
정답 코드 및 설명
먼저, 특정한 간선 하나를 제거하고, 제거한 간선의 가중치와 같은 가중치를 가지는 간선을 하나 추가했을 때 만들어지는 새로운 트리의 지름으로 가능한 최댓값을 구하자.
트리에서 간선을 하나 제거하면 연결 요소가 두 개인 그래프가 된다.
처음 트리에 사이클이 없으므로, 간선을 제거해도 사이클이 없다. 따라서 각각의 연결 요소는 트리가 되고, 지름을 구할 수 있다.
이제 간선을 하나 추가해서 만든 트리의 지름으로 가능한 최댓값은 각 트리의 지름 + 추가될 간선의 가중치이다.
트리 A에서 가장 멀리 떨어진 두 노드가 a1, a2이고, 트리 B에서 가장 멀리 떨어진 두 노드가 b1, b2라고 하자.
트리 A의 노드 a3와 트리 B의 노드 b3를 가중치 w인 간선으로 연결했다고 하자.
트리 A 안의 노드 a와 트리 B 안의 노드 b에 대해, a와 b 사이의 거리는 a와 a3 사이의 거리 + a3와 b3 사이의 거리 + b3와 b 사이의 거리를 넘을 수 없다. a와 a3 사이의 거리는 트리 A의 지름 이하이고, b3와 b 사이의 거리는 트리 B의 지름 이하이며, a3와 b3 사이의 거리는 w이다.
따라서 전체 트리의 지름은 항상 트리 A의 지름 + 트리 B의 지름 + w 이하이다.
전체 트리의 지름 = 트리 A의 지름 + 트리 B의 지름 + w인 경우로는 a1 = a3, b1 = b3, a = a2, b = b2인 경우가 있다.
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
101
102
103
104
105
106
107
108
109
110
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
public class BOJ12912 {
int n;
ArrayList<Node>[] graph;
Edge[] edges;
long[] diameter;
static class Edge {
int from, to;
long cost;
Edge(int from, int to, long cost) {
this.from = from;
this.to = to;
this.cost = cost;
}
public boolean equals(int from, int to) {
return (from == this.from && to == this.to) || (from == this.to && to == this.from);
}
}
void input() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(br.readLine());
edges = new Edge[n - 1];
graph = new ArrayList[n];
for (int i = 0; i < n; i++)
graph[i] = new ArrayList<>();
diameter = new long[n];
StringTokenizer st;
int from, to, cost;
for (int i = 0; i < n - 1; i++) {
st = new StringTokenizer(br.readLine());
from = Integer.parseInt(st.nextToken());
to = Integer.parseInt(st.nextToken());
cost = Integer.parseInt(st.nextToken());
graph[from].add(new Node(to, cost));
graph[to].add(new Node(from, cost));
edges[i] = new Edge(from, to, cost);
}
}
int edgeNo;
void maxDist(int start) {
int size = graph[start].size();
for (int i = 0; i < size; i++) {
Node curr = graph[start].get(i);
if (edges[edgeNo].equals(start, curr.node)) continue;
if (diameter[curr.node] != -1) continue;
diameter[curr.node] = diameter[start] + curr.cost;
maxDist(curr.node);
}
}
static class Node {
int node;
long cost;
public Node(int node, long cost) {
this.node = node;
this.cost = cost;
}
}
Node max(int start) {
int index = 0;
long max = -1;
Arrays.fill(diameter, -1);
diameter[start] = 0;
maxDist(start);
for (int i = 0; i < diameter.length; i++) {
if (diameter[i] > max) {
max = diameter[i];
index = i;
}
}
return new Node(index, max);
}
long diameter(int start) {
int first = max(start).node;
return max(first).cost;
}
long diameter() {
return diameter(edges[edgeNo].from) + diameter(edges[edgeNo].to) + edges[edgeNo].cost;
}
void solution() throws IOException {
input();
long diameter = 0;
for (edgeNo = 0; edgeNo < n - 1; edgeNo++) {
diameter = Math.max(diameter, diameter());
}
System.out.println(diameter);
}
public static void main(String[] args) throws IOException {
new BOJ12912().solution();
}
}
댓글남기기