Key
- 양의 가중치가 있는 트리가 주어졌을 때 두 노드 사이의 경로 중 가장 긴 경로 구하기
- 노드 개수는 최대 1만개
- 루트 노드는 항상 1번
Idea
트리의 지름을 구하는 방법은 다음과 같다.
- 루트 노드에서 가장 먼 노드 A를 찾는다.
- 노드 A에서 가장 먼 노드 B를 찾는다.
- A와 B 사이의 경로가 트리의 지름이 된다.
이 문제는 DFS를 두번 활용하면 된다. 우선 두 노드 중 첫번째 노드를 구해보자. 편의상 두 노드를 A, B라고 하겠다. A노드는 루트노드에서 가장 먼 노드를 찾으면 된다. 처음에 왜 루트 노드에서 가장 먼 노드가 A가 되는건지 이해를 못했는데, 간선의 가중치가 양의 정수라서 그렇다. 때문에 거치는 간선 개수가 많아질 수록 경로 길이도 길어진다. 따라서 말단 노드 중 하나가 A 노드일 확률이 높고, 같은 지점에서 출발했을 때 가장 경로 길이가 긴 말단 노드를 구하기 위해 위와 같은 방법을 쓰는 것이다.
다음으로, A에서 다시 가장 먼 노드를 찾으면 된다. 첫 번째 탐색에서 가장 먼 노드를 찾는 과정에서 이미 가능한 최장 경로의 한 끝을 찾았기 때문이다. 이는 A에서 B로 가는 경로가 트리에서 가장 긴 경로라는 것을 보장한다.
Code
#include <iostream>
#include <vector>
using namespace std;
bool visited[10001] = { false, };
vector<pair<int, int>>node[10001];
int maxValue=0, maxNode = 0;
void DFS(int x, int value) {
int size = node[x].size();
visited[x] = true;
if (maxValue < value) {
maxValue = value;
maxNode = x;
}
for (int i = 0; i < size; i++) {
if (!visited[node[x][i].first]) {
DFS(node[x][i].first, value+node[x][i].second);
}
}
}
int main() {
int N = 0;
int S = 0, E = 0, W = 0;
cin >> N;
for (int i = 0; i < N-1; i++) {
cin >> S >> E >> W;
node[S].push_back(make_pair(E, W));
node[E].push_back(make_pair(S, W));
}
DFS(1, 0);
maxValue=0;
for (int i = 0; i <= N; i++) {
visited[i] = false;
}
DFS(maxNode, 0);
cout << maxValue << "\n";
return 0;
}
회고
더보기
DFS를 두번 쓰는 문제를 처음 풀어봐서 어떻게 풀지 감이 안잡혔다. 나중에 다시 풀어봐야겠다. 그리고 fill을 이용해서 배열을 초기화할 수 있다는 걸 처음 알았다. algorithm 헤더를 추가하면 fill(visited, visited+N+1, false) 이렇게 해서 초기화할 수 있다고 한다. 벡터에서만 사용할 수 있는건줄 알았다.
'나도 공부한다 > 알고리즘' 카테고리의 다른 글
[백준] 9663. N-Queen (C++) (0) | 2024.07.16 |
---|---|
[백준] 1018. 체스판 다시 칠하기 (C++) (0) | 2024.07.14 |
[백준] 1629. 곱셈 (C++) (0) | 2024.06.17 |
[백준] 14940. 쉬운 최단거리 (C++) (1) | 2024.06.16 |
[백준] 16113. 시그널 (C++) (0) | 2024.06.15 |