강한 연결 요소란
방향 그래프에서 두 정점 \(u, v\)가 서로 도달 가능하면(\(u \to v\) 경로와
\(v \to u\) 경로가 모두 존재) 같은 그룹에 둔다. 이렇게 묶인 극대 집합을
강한 연결 요소(SCC, Strongly Connected Component) 라 한다.
각 SCC를 하나의 정점으로 합치면, 남는 간선은 SCC 사이의 방향만 남는다. 이렇게
만든 그래프를 응축 그래프(condensation) 라 하며, 항상 DAG가 된다.
만약 사이클이 생긴다면 그 사이클에 속한 SCC들은 서로 도달 가능하므로 하나의
SCC로 합쳐졌어야 하기 때문이다. 이 "방향 그래프 → DAG" 환원이 SCC의 가장 큰
가치다.
코사라주 알고리즘
가장 이해하기 쉬운 방법은 두 번의 DFS다.
- 원래 그래프에서 DFS하며 끝나는 순서(post-order) 로 정점을 스택에 쌓는다.
- 모든 간선을 뒤집은 역방향 그래프에서, 스택을 위에서부터 꺼내며 아직
방문 안 한 정점에서 DFS한다. 한 번의 DFS로 닿는 정점들이 곧 하나의 SCC다.
핵심은 "끝나는 시각이 가장 늦은 정점은 응축 DAG의 소스(source) SCC에
속한다"는 사실이다. 역방향 그래프에서 그 정점부터 탐색하면 같은 SCC만 닿고
다른 SCC로 새어 나가지 않는다.
타잔 알고리즘
코사라주가 두 번 도는 반면, 타잔은 한 번의 DFS로 끝낸다. 각 정점에 방문
순서 disc와, 그 정점에서 DFS 트리/역방향 간선을 타고 올라갈 수 있는 가장
이른 정점의 순서 low를 매긴다.
- DFS 진입 시 정점을 스택에 push하고
disc = low = ++timer. - 트리 간선 \(u \to v\) 이후
low[u] = min(low[u], low[v]). - 아직 스택에 있는 역방향 간선 \(u \to v\)이면
low[u] = min(low[u], disc[v]). - DFS 종료 시
low[u] == disc[u]이면 \(u\)가 SCC의 루트다. 스택에서 \(u\)가
나올 때까지 pop한 정점들이 한 SCC를 이룬다.
low[u] == disc[u]라는 조건은 "\(u\)의 서브트리에서 \(u\)보다 위로 올라가는 길이
없다"는 뜻이고, 이는 곧 \(u\)가 자기 SCC의 진입점임을 의미한다.
복잡도
코사라주와 타잔 모두 정점·간선을 상수 번씩 방문하므로 \(O(V + E)\)다. 타잔이
상수가 더 작고 한 번에 끝나서 실전에서 선호되지만, 코사라주는 직관적이고
응축 그래프의 위상 순서를 자연스럽게 준다는 장점이 있다.