알고리즘

[백준 1967] C++ 트리의 지름

나폴나폴 2024. 2. 13. 04:48
728x90

1. 문제


2. 분석


맨 처음엔 루트에서 가장 먼 두 점을 구해서,

그 두 점에서 부터 역으로 부모 노드 쪽으로 올라가다 같은 부모 노드를 보고 있게 되면

(가장 먼 두 점까지의 거리의 합) - (2 * 부모 노드까지의 거리의 합) 의 형태로 구하려 했으나 실패.

 

하지만, 루트에서 가장 먼 한 점은 결국 이 트리의 지름의 한 점이 된다는 것은 확실하다.

그리고 그 점에서 다시 가장 먼 한 점을 구하면, 지름의 나머지 한 점을 구할 수 있게 된다!

 

이 아이디어만 가지면 쉽게 구할 수 있었을 텐데, 생각이 나질 않았다.

 

*해당 아이디어는 아래 블로그에서 채용했다.

https://codingwell.tistory.com/61

 

[ 백준 ] 1967번 - 트리의 지름 ( C++ )

dfs를 이용하여 푸는 문제이다. 풀이를 생각해보는데 쉽게 떠오르지 않았다. 고민 끝에 다른사람의 풀이를 참고하였다. https://www.acmicpc.net/problem/1967 1967번: 트리의 지름 파일의 첫 번째 줄은 노드

codingwell.tistory.com

3. 풀이


트리 이므로 부모-자식 간의 edge만 존재하니, 다익스트라처럼 여러 번 연산을 하지 않아도 된다.

단지, 방문했는지 여부를 체크하면 끝!

 

가장 먼 점을 구할 땐, dfs를 사용하여 계산한다.


4. 코드


#include <iostream>
#include <vector>
#include <string.h>
using namespace std;

vector<pair<int, int>> V[10001];
bool visited[10000] = { false, };

int res = 0;
int endPoint = 0;

void dfs(int start, int len) {
	if (visited[start]) return;

	visited[start] = true;

	if (res < len) {
		res = len;
		endPoint = start;
	}

	for (int i = 0; i < V[start].size(); i++)
	{
		dfs(V[start][i].first, len + V[start][i].second);
	}
}

int main()
{
	int n;
	cin >> n;

	if (n == 1)
	{
		cout << 0;
		return 0;
	}

	int parent, child, cost;

	// edge 수는 n-1.
	for (int i = 0; i < n - 1; i++)
	{
		cin >> parent >> child >> cost;

		V[parent].push_back({ child, cost });
		V[child].push_back({ parent, cost });
	}
	
	// 루트에서 제일 먼 점 A구하기.
	dfs(1, 0);

	memset(visited, false, sizeof(visited));

	// 점 A에서 가장 먼 점 구하기.
	dfs(endPoint, 0);

	cout << res;
}

 

V라는 벡터에 저장할 때, V[parent] 말고도, V[child]로 한번 더 저장해서

부모 -> 자식 / 자식 -> 부모 노드 방향 등 어느 방향에서 접근하더라도 계산 가능하도록 한 점이 인상적이었다!

반응형