문제 링크
- http://icpc.me/14176
사용 알고리즘
- Centroid Decomposition
- FFT
풀이
cnt[k] = 길이가 k인 경로의 개수 라고 정의합시다.
cnt[1]부터 cnt[N-1]까지 모두 구해주면 문제를 풀 수 있습니다.
$O(N^2)$가지의 경로를 모두 고려해야 하기 때문에 센트로이드를 생각할 수 있습니다.
centroid $C$를 지나는 모든 경로들을 고려해봅시다.
어떤 경로가 $C$를 지난다는 것은, $C$를 제거했을 때 나눠지는 서브트리 $T_1, T_2, \ldots , T_x$가 있을 때 서로 다른 서브트리 $T_i, T_j$에서 정점을 하나씩 선택해서 이은 경로를 의미합니다.
$T_i$에 있는 정점 중 센트로이드 $C$와 거리가 $k$만큼 떨어진 정점의 개수를 subtree[i][k] 라고 합시다.
$T_i$에 있는 정점 하나와 $T_j$에 있는 정점 하나를 이어서 만든 길이가 $k$인 경로의 개수는 subtree[i][a] × subtree[j][k-a] 로 계산할 수 있습니다. 그러므로 두 개의 서브트리를 선택해서 모든 경로의 길이를 고려해주는 것은 convolusion의 형태로 나타낼 수 있고, 이는 FFT로 계산해줄 수 있습니다.
즉, $T_1$부터 $T_x$ 까지 모두 보면서 (subtree[1] + subtree[2] + … + subtree[i-1])과 subtree[i]를 곱한 결과를 cnt에 누적시켜주면 됩니다.
Centroid Decomposition과 FFT를 열심히 구현하면 풀리는 문제입니다.
전체 코드
1 |
|