1967번: 트리의 지름
파일의 첫 번째 줄은 노드의 개수 n(1 ≤ n ≤ 10,000)이다. 둘째 줄부터 n번째 줄까지 각 간선에 대한 정보가 들어온다. 간선에 대한 정보는 세 개의 정수로 이루어져 있다. 첫 번째 정수는 간선이 ��
www.acmicpc.net
간단한 문제였다. 모든 정점을 시작점으로 bfs나 dfs를 수행하여 그중 최댓값을 찾으면 정답을 받을 수 있다.
하지만 이 문제를 더 빠르게 풀 수 있는 방법이 존재한다고 한다.
뿌리노드인 1번 노드에서 가장 멀리 떨어진 정점을 찾고, 그 정점을 시작점으로 하여 가장 멀리 떨어진 정점까지의 거리가 곧 트리의 지름이 된다. 따라서 탐색을 2번 수행하므로 O(n) 시간에 문제를 해결할 수 있다.
자세한 증명은 구사과님의 블로그에 설명되어 있다.
트리의 지름 (Diameter of tree)
트리에서 정점 두개를 잡고, 거리를 재본다. n^2 쌍의 개수만큼 거리들이 나올텐데... 이 중 가장 거리가 긴 놈을 트리의 지름이라 부른다. dfs 2번 돌려서 O(n)에 해결할 수 있다. 알고리즘 문제 해��
koosaga.com
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
int N;
vector<vector<pair<int, int>>> adj(10001);
bool visited[10001];
pair<int, int> bfs(int start) {
queue<pair<int, int>> q;
q.push({ start, 0 });
visited[start] = true;
pair<int, int> ret = { 0,0 };
while (!q.empty()) {
int here = q.front().first;
int cost = q.front().second;
q.pop();
if (ret.second < cost)
ret = { here, cost };
for (int i = 0; i < adj[here].size(); i++) {
int there = adj[here][i].first;
int nextCost = cost + adj[here][i].second;
if (!visited[there]) {
visited[there] = true;
q.push({ there, nextCost });
}
}
}
return ret;
}
int main(void) {
cin >> N;
for (int i = 0; i < N - 1; i++) {
int a, b, c;
cin >> a >> b >> c;
adj[a].push_back({ b, c });
adj[b].push_back({ a, c });
}
// find maximum node
int maxNode = bfs(1).first;
memset(visited, false, sizeof(visited));
// get diameter
int diameter = bfs(maxNode).second;
cout << diameter << endl;
return 0;
}

알고리즘 200일 프로젝트 - 168 day
'알고리즘 > BOJ' 카테고리의 다른 글
백준 1504번: 특정한 최단 경로 (0) | 2020.09.24 |
---|---|
백준 9466번: 텀 프로젝트 (0) | 2020.09.23 |
백준 9019번: DSLR (0) | 2020.09.23 |
백준 1238번: 파티 (0) | 2020.09.22 |
백준 2146번: 다리 만들기 (0) | 2020.09.22 |