"트리에 존재하는 모든 경로 중 가장 긴 것의 거리" 를 구하는 문제를 마주쳤을 때, 어떤 방식으로 이를 해결해야 할까?
브루트포스적인 접근 방식으로 bfs(넓이 우선 탐색)을 통해 모든 정점에서의 최대 거리를 구해야 할까?
고민을 하던 중 주변의 도움을 받아 알게 된 해결 방법을 공부해보고자 한다.
프로그래밍을 공부하는 학생이 지식 정리 및 공유를 위해 작성한 글으로, 정확하지 않은 내용이 있을 수 있습니다. 지적과 지식 공유는 환영합니다!
트리 는 그래프에 포함되어 있는 개념이다.
그래프 중 사이클을 이루지 않고 모든 노드가 연결되어 있는 그래프를 트리라고 한다.
위와 같은 꼴이 트리의 대표적 예시이다.
위의 모양새를 가진 트리의 지름은 무엇이라고 할 수 있을까?
노드 3과 노드 6을 연결하는, 가장 긴 경로가 바로 이 트리의 지름이 된다고 할 수 있겠다.
위 경로는 이 트리에서 가장 긴 거리이기 때문에, 다른 모든 노드들은 위 두 노드를 지름으로 갖는 원 안에 존재한다.
트리의 지름을 구하는 방법은 다음과 같다.
이때, 가중치를 가지는 트리인 경우, 가중치가 가장 큰 경로가 거리가 먼 것이라고 생각하면 된다.
해결 방법은 꽤 단순하다고 할 수 있으나, 어떻게 그것이 최장거리이자 트리의 지름인지는 단번에 이해하기 힘들다.
나의 경우도 이해하는 데 꽤 시간이 걸렸는데, 그 과정에서 가장 도움이 많이 되었던 포스트를 소개하고자 한다.
https://blog.myungwoo.kr/112
감사합니다 :-)
위 포스트를 기반으로, 내가 이해한 바를 정리해보면 다음과 같다.
위의 방법으로 구한, 트리의 지름으로 가정하는 노드 와 노드 가 있다. 그리고 실제 트리의 지름인 노드 와 노드 가 있다.
이 네가지 노드는 다음과 같은 관계일 수 있다.
노드 가 노드 혹은 노드 중 하나와 일치한다
즉, 노드 는 트리의 지름의 양 끝 노드 중 하나이다.
노드 가 노드 혹은 노드 중 하나와 일치한다
즉, 노드 는 트리의 지름의 양 끝 노드 중 하나이다.
노드 와 노드 둘 다 트리의 지름의 양 끝 노드가 아니다.
1번과 2번, 노드 또는 노드 가 트리의 지름을 이루는 양 끝 노드라고 하면, 각 노드로부터 가장 먼 노드인 또는 또한 트리의 지름의 양 끝 노드이기 때문에 이 방법은 옳은 방식일 것이다.
따라서, 3번의 경우가 존재하지 않음을 증명해낸다면, 해당 방법은 옳다고 할 수 있다.
3번일 때, 두 가지 경우를 생각할 수 있다.
따라서 3번은 존재하지 않으며, 위 방법은 옳다.
증명과 이해를 하는 과정은 힘들었지만, 이를 적용하는 것은 이해보다 쉬울 지도 모른다.
트리의 지름을 구하는 방법과 그래프의 넓이 우선 탐색(bfs)을 이용해 다음 문제를 풀어보았다.
[BOJ 1167: 트리의 지름] https://www.acmicpc.net/problem/1167
[BOJ 1967: 트리의 지름] https://www.acmicpc.net/problem/1967
두 문제는 노드 개수의 범위가 10배 정도 차이나는 것과 입력 방식이 다르다는 점을 제외하고 거의 일치하다고 볼 수 있다. 트리의 지름을 이용하면, bfs를 두 번만 사용하면 되기 때문에, 두 문제를 무난하게 해결해낼 수 있다.
1967번 의 경우, 임의의 노드에서 시작하기 때문에, 입력을 받은 후, 양방향으로 각각의 간선을 저장해줘야 한다. 1167번 은 두 방향 모두 입력으로 주어지기에 크게 신경쓰지 않아도 된다.
나의 경우, bfs (넓이 우선 탐색)를 진행할 때, pair
에 노드 번호, 경로의 가중치를 저장한 queue
를 사용했다. queue
에서 노드를 pop
할 때 해당 노드의 가중치의 값이 최대인 경우 미리 저장해둔 뒤, bfs가 끝나면 가중치가 최대인 노드의 정보를 리턴값으로 주었다.
따라서, 처음은 임의의 노드로 bfs를 진행하고, 리턴값으로 받은 가중치가 최대인 노드에서부터 bfs를 다시 진행하여 해당 노드로부터 가장 먼 노드까지의 가중치를 출력하여 해결했다.
Github Solution Link; BOJ 1167
Github Solution Link; BOJ 1967