DOJ logoDOJ
题目
最近添加的题目收藏的题目Workbooks
分类DLC比赛小组团队讨论区
排名
解题数量排行榜连续解题排名DOJ Power 排行榜
评测状态
征题登录注册
DOJ logoDOJ

支持 OI 子任务计分、Elo 等级分和 Discord 认证的社区在线评测系统。

题目
题目列表分类
社区
比赛排名讨论区公告举办外部比赛指南
账号
登录注册评测状态
政策
服务条款DLC 使用规则隐私政策API 文档语言运行环境比赛排名奖励评级与表现
© 2026 DOJ
保留所有权利
题解

Finding dfs tree

返回题目

题解

처음에는 각 정점을 하나의 컴포넌트로 본다. 이미 선택한 트리 간선으로 합쳐진 정점들은 하나의 컴포넌트로 수축한다.

현재 컴포넌트 BBB의 진입 간선은 꼬리가 BBB 밖에 있고 머리가 BBB 안에 있는 원래 방향 간선이다. 진입하는 서로 다른 컴포넌트의 수가 아니라, 방향 간선의 개수 자체를 센다는 점에 주의해야 한다.

진입 간선이 정확히 하나인 컴포넌트 BBB를 찾는다. 그 유일한 간선을 u→vu \to vu→v라 하고, uuu가 속한 컴포넌트를 AAA라 하자. u→vu \to vu→v를 트리 간선으로 선택하여 Pv=uP_v=uPv​=u로 정하고, AAA와 BBB를 하나의 컴포넌트로 합친다. 새 컴포넌트의 루트 정점은 기존 AAA의 루트 정점이다.

이 과정을 더 이상 수행할 수 없을 때까지 반복한다.

정당성

컴포넌트 BBB의 진입 간선이 u→vu \to vu→v 하나뿐일 때 BBB를 AAA 아래에 붙였다고 하자. 두 컴포넌트 사이에서 AAA 쪽에서 BB 쪽으로 향하는 간선은 이 간선 하나뿐이다. 따라서 두 컴포넌트가 합쳐질 때 새로 내부 간선이 되는 다른 모든 간선은 에서 로 향한다. 이 간선들은 새 트리에서 자손 쪽 컴포넌트에서 조상 쪽 컴포넌트로 향한다. 기존 컴포넌트 내부의 조건도 귀납적으로 유지된다.

반대로 유효한 트리가 존재하고 컴포넌트가 둘 이상이라고 하자. 선택된 트리 간선만 남겨 컴포넌트들을 하나의 정점으로 수축하면 컴포넌트들 사이에도 루트 있는 트리가 생긴다. 이 트리의 리프 컴포넌트에는 부모 컴포넌트에서 오는 트리 간선 하나만 진입할 수 있다. 리프 컴포넌트 밖에는 그 컴포넌트의 자손이 없으므로, 트리에 속하지 않은 역방향 간선이 추가로 진입할 수도 없다. 따라서 진입 간선이 정확히 하나인 컴포넌트가 반드시 존재한다.

진입 간선이 하나인 컴포넌트를 먼저 수축하는 선택들은 서로 교환할 수 있다. 한 수축은 관련되지 않은 다른 컴포넌트의 진입 간선 집합을 바꾸지 않으며, 두 관련 컴포넌트를 합친 것으로만 치환된다. 따라서 어떤 순서로 가능한 수축을 골라도, 유효한 트리가 존재한다면 최종적으로 하나의 컴포넌트에 도달한다.

최종적으로 컴포넌트가 하나라면 선택한 N−1N-1N−1개의 간선이 조건을 만족하는 트리이다. 컴포넌트가 둘 이상인데 진입 간선이 하나인 컴포넌트가 없다면 유효한 트리는 존재하지 않는다.

효율적인 구현

각 컴포넌트에 다음 정보를 저장한다.

  • 컴포넌트에 속한 정점 목록
  • 컴포넌트로 들어오는 외부 간선 번호의 해시 집합
  • 아직 부모가 정해지지 않은 컴포넌트의 루트 정점

두 컴포넌트를 합칠 때 정점 수가 작은 쪽을 큰 쪽으로 옮긴다.

작은 컴포넌트의 모든 정점에서 나가는 간선을 확인하면, 작은 컴포넌트에서 큰 컴포넌트로 향하여 내부 간선이 되는 간선을 큰 컴포넌트의 진입 간선 집합에서 지울 수 있다. 작은 컴포넌트의 진입 간선 집합도 큰 쪽으로 옮기되, 꼬리가 큰 컴포넌트에 있는 간선은 내부 간선이므로 버린다.

작은 쪽의 정점 수는 이동할 때마다 두 배 이상이 된다. 따라서 각 정점과 각 간선은 O(log⁡N)O(\log N)O(logN)번만 처리된다. 해시 집합을 사용하면 기대 시간 복잡도는 O((N+M)log⁡N)O((N+M)\log N)O((N+M)logN)이고, 공간 복잡도는 O(N+M)O(N+M)O이다.

B
BBB
AAA
(
N
+
M)