문제 링크
- https://icpc.me/26415
사용 알고리즘
- 트리 디컴포지션
시간복잡도
- $O(N)$
풀이
halin graph의 treewidth가 3 이하인 tree decomposition을 구하는 문제입니다.
트리의 가장 왼쪽 리프 정점 $l$과 오른쪽 리프 정점 $r$이 연결되어야 하므로, $l, r$을 모두 포함하는 bag이 존재해야 합니다. 각 정점 $v$를 루트로 하는 서브 트리의 tree decomposition에서, 루트 정점의 bag에 $(v, l, r)$을 저장하는 방식으로 만들어 봅시다.
$v$가 리프 정점이면 $l=r=v$입니다. 따라서 $(v, v, v)$를 만들면 됩니다.
이제 $v$가 한 개 이상의 자식 정점을 갖고 있는 경우를 생각해 봅시다. $v$는 $v$의 자식 정점 $c$와 연결되어 있으므로 $v, c$를 포함하는 bag이 존재해야 합니다. $(c,l,r)$의 부모 정점으로 $(v,l,r,c)$를 달면 됩니다. $c$와 연결된 모든 정점을 처리했으므로 더 이상 $c$를 신경쓸 필요가 없다는 것에 주목합시다.
남은 것은 자식 정점의 정보 $(v,l_1,r_1,c_1), (v,l_2,r_2,c_2), \cdots, (v,l_k,r_k,c_k)$가 주어졌을 때, 이 정보들을 하나의 정보 $(v, l, r)$로 합치는 것 뿐입니다. 인접한 두 서브 트리를 합치는 방식으로 진행합니다.
$(v,s,e,c_1)$과 $(v,l,r,c_2)$를 합치는 방법을 생각해 봅시다. $c_1,c_2$를 무시할 수 있으므로 dummy를 의미하는 $d_1,d_2$로 치환해서 $(v,s,e,d_1), (v,l,r,d_2)$로 표기하겠습니다.
왼쪽 서브 트리의 오른쪽 리프 정점 $e$는 오른쪽 서브 트리의 왼쪽 리프 정점 $l$과 연결되어야 합니다. $(v,s,e,d_1) \rightarrow (v,s,e,l)$을 만들어 봅시다. $e$와 연결된 모든 정점을 처리했기 때문에 이제부터 $e$를 무시할 수 있습니다.
지금 만든 bag인 $(v,s,e,l)$과 두 번째 서브 트리를 담당하는 bag인 $(v,l,r,d_2)$ 모두 $l$을 포함하고 있기 때문에, 두 bag은 $l$을 포함하는 bag들로 연결되어야 합니다. $(v,s,r,l)$을 만들어서 두 bag과 연결하면 됩니다. 이제 $l$도 무시할 수 있습니다.
합쳐진 두 서브 트리의 왼쪽 리프 정점인 $s$와 오른쪽 리프 정점인 $r$이 같은 bag에 포함되었으므로 두 서브 트리를 성공적으로 합쳐졌습니다. 또한 4번째 원소는 무시해도 되는 정점이기 때문에 이 절차를 반복해서 모든 서브 트리를 합칠 수 있습니다.
서브 트리를 모두 합치면 $(v,l,r,d)$ 꼴의 bag 하나를 얻을 수 있습니다. 최종적으로 원하는 결과는 $(v,l,r)$이므로 $(v,l,r,d)$의 부모 bag $(v,l,r)$을 만들어서 연결합시다.
이 과정을 구현하면 $O(N)$ 시간에 treewidth가 3인 tree decomposition을 구할 수 있습니다.
전체 코드
1 |
|