도전

시간 제한2초메모리 제한512 MB

요약
정점이 floor(sqrt(n))개 이상의 조각에 속하도록, 중심을 재귀적으로 제거하는 분해에서 깊이가 깊어지는 트리를 n개 이하의 정점으로 구성한다.
난이도

어려움10점 중 8점

유형
트리, 그리디, 수학, 구현
정답자
아직 제출이 없습니다

문제

트리를 다루는 많은 프로그래밍 대회 문제는 센트로이드 분해로 해결한다. 트리가 주어지면 먼저 센트로이드를 찾는다. 센트로이드란, 트리에서 그 정점을 제거한 뒤 남는 조각들이 모두 원래 트리 정점 수의 절반 이하를 가지는 정점이다. 그런 다음 찾은 센트로이드를 트리에서 제거하고, 남은 각 조각에 대해 이 과정을 재귀적으로 적용한다. 각 조각의 크기는 한 단계마다 적어도 절반으로 줄어들므로, 정점이 n개인 트리에서 단계는 많아야 log2(n) + 1개다. 다시 말해, 임의의 정점에 대해 그 정점을 포함하면서 알고리즘 도중 처리되는 조각은 많아야 log2(n) + 1개다.

다른 참가자가 센트로이드 분해에서 버그를 만들었다는 사실을 알아챘다. 그 참가자는 센트로이드를 찾는 대신 각 단계에서 트리의 중심(center)을 찾는다. 중심이란, 다른 정점까지의 최대 거리를 최소화하는 정점이다. 더 형식적으로, dij를 정점 i와 j 사이의 거리(트리 간선 수)라고 하면, r = mini(maxj(dij))를 트리의 반지름이라 하고, maxj(dkj) = r인 정점 k를 트리의 중심이라 한다.

이 버그 때문에 분해 단계가 log2(n) + 1개보다 많아질 수 있다. 이 풀이에 도전하려면, 이 '중심 분해'가 적어도 ⌊√n⌋개의 단계를 가지는 트리를 정점 수 n개 이하로 만들어야 한다. 더 정확히는, 분해 도중 처리되는 서로 다른 부분집합에 적어도 ⌊√n⌋번 속하는 정점이 하나 이상 있어야 한다.

어떤 단계의 트리에 중심이 여러 개 있으면, 분해는 정점 번호가 가장 작은 중심을 제거할 중심으로 선택한다고 가정할 수 있다.

입력

입력은 한 줄로 이루어지며, 정수 n이 주어진다. 1 ≤ n ≤ 100000.

출력

출력 첫 줄에 트리의 정점 수 m을 출력한다. 1 ≤ m ≤ n. 다음 m − 1개 줄에 트리의 간선을 설명한다. 각 간선은 연결하는 두 정점의 번호로 나타낸다. 정점은 1부터 m까지 번호가 매겨진다.

트리의 정점 중 적어도 하나는, 중심(여러 개면 정점 번호가 가장 작은 것)을 골라 트리에서 제거하고 남은 모든 조각에 이 과정을 재귀적으로 적용하는 과정에서 적어도 ⌊√n⌋개의 서로 다른 조각에 속해야 한다.

예제1

  1. 예제 1

    입력
    4
    
    예상 출력
    3
    1 2
    2 3