도구스개발

강한 연결 요소(SCC) 계산기

방향 그래프의 간선을 넣으면 서로 오갈 수 있는 정점 묶음을 타잔 알고리즘으로 찾고, 묶음끼리 축약한 DAG와 low-link 값을 함께 보여 줍니다. 모듈 사이 순환 의존이 어디에 있는지 그대로 확인할 수 있습니다.

한 줄에 하나씩 「A -> B」로 적습니다. 화살표 대신 공백이나 쉼표도 됩니다. 정점은 26개까지.

순환하는 묶음

1개

정점 4개가 묶음 2개로 갈렸고, 그중 1개가 순환합니다. 가장 큰 묶음에 3개가 들어 있습니다.

정점4개
강한 연결 요소2개
순환하는 묶음1개
가장 큰 묶음3개
축약 그래프 간선1개

묶음 — 축약 그래프의 위상 순서

#0 A, B, C· 순환 (3개가 서로 오감)
#1 D· 순환 없음

번호가 작을수록 앞입니다. 타잔은 묶음을 축약 그래프의 위상 역순으로 뱉으므로 뒤집어 매기면 그대로 위상 순서가 됩니다. 파랗게 칠한 묶음이 순환하는 묶음이고, 그 안의 정점들은 서로를 끌어안고 있어 따로 떼어 낼 수 없습니다.

축약 그래프 (반드시 DAG)

#0 → #1

묶음을 정점 하나로 줄이면 순환이 남을 수 없습니다. 두 묶음 사이에 양방향 길이 있으면 애초에 한 묶음이었을 테니 모순이기 때문입니다. 그래서 위상 정렬이 실패하는 그래프라도 SCC로 축약하면 반드시 정렬됩니다. 빌드 순서나 모듈 계층을 정할 때 쓰는 방법이 이것입니다.

타잔의 low-link 값

정점indexlow뿌리묶음
A00#0
B10#0
C20#0
D33#1

index는 몇 번째로 발견됐는지, low는 그 정점에서 아직 탐색 중인 정점까지 타고 갈 수 있는 가장 작은 index입니다. 자식을 다 보고 돌아왔을 때 low = index이면 그 정점이 묶음의 뿌리입니다. 자기보다 먼저 발견된 정점으로 돌아가는 길이 하나도 없다는 뜻이라, 스택에 자기 위로 쌓인 것들이 통째로 한 묶음이 됩니다.

타잔에서 가장 흔한 실수는 이미 다른 묶음으로 확정된 정점을 보고 low를 낮추는 것입니다. 그러면 서로 다른 묶음이 하나로 붙어 버립니다. 「아직 스택에 남아 있는가」를 따로 표시해 두고 그 경우에만 낮춰야 합니다. 위 예시 중 「묶음 넷」을 눌러 보면, 그 표시를 빠뜨렸을 때 네 묶음이 하나로 뭉개지는 구조를 볼 수 있습니다.
정점 하나짜리 묶음은 보통 순환이 아니지만, 자기 자신으로 가는 간선이 있으면 크기가 1이어도 순환입니다. 순환 의존을 찾는 것이 목적이라면 이 경우를 빠뜨리면 안 됩니다. 모듈이 자기를 import 하는 일은 드물지만 빌드 규칙이나 상태 기계에서는 흔합니다.
그래프 탐색 계산기가 세는 「연결 요소」는 방향을 무시했을 때의 값이라 여기와 다릅니다. A → B만 있고 되돌아오는 길이 없으면 방향을 무시하면 한 덩어리지만, 강한 연결 요소로는 둘로 갈립니다. 순환 의존을 찾을 때 필요한 것은 이쪽입니다.

사용 방법

  1. 1간선을 한 줄에 하나씩 「A -> B」로 적습니다. 공백이나 쉼표로 나눠도 됩니다.
  2. 2묶음 목록에서 파랗게 칠한 것이 순환하는 묶음입니다.
  3. 3축약 그래프를 보면 묶음끼리는 한 방향으로만 이어지는 것을 확인할 수 있습니다.
  4. 4low-link 표에서 low = index인 정점(뿌리 표시)이 묶음을 확정한 자리입니다.

자주 묻는 질문

방향 그래프에서 서로 오갈 수 있는 정점들의 묶음입니다. u에서 v로도, v에서 u로도 갈 수 있는 관계는 동치관계라 정점 전체가 묶음으로 깔끔히 갈립니다. 모듈 사이 순환 의존을 찾는 일이 정확히 이 계산이며, 한 묶음에 든 모듈들은 서로를 끌어안고 있어 따로 떼어 낼 수 없습니다.

그 정점에서 아직 탐색 중인(스택에 남아 있는) 정점까지 타고 갈 수 있는 가장 작은 발견 순번입니다. 자식을 다 보고 돌아왔을 때 low = index이면 그 정점이 묶음의 뿌리입니다. 자기보다 먼저 발견된 정점으로 돌아가는 길이 하나도 없다는 뜻이라, 스택에 자기 위로 쌓인 것들이 통째로 한 묶음이 됩니다.

이미 다른 묶음으로 확정된 정점을 보고 low를 낮추는 것입니다. 그러면 서로 다른 묶음이 하나로 붙어 버립니다. 「아직 스택에 남아 있는가」를 따로 표시해 두고 그 경우에만 낮춰야 하며, 이미 확정된 정점을 향하는 간선은 무시해야 합니다.

두 묶음 사이에 양방향 길이 있으면 애초에 한 묶음이었을 테니 모순이기 때문입니다. 그래서 위상 정렬이 실패하는 그래프라도 SCC로 축약하면 반드시 정렬됩니다. 빌드 순서나 모듈 계층을 정할 때 쓰는 방법이 이것입니다. 덧붙여 타잔은 묶음을 축약 그래프의 위상 역순으로 뱉으므로, 뒤집기만 하면 따로 정렬할 필요도 없습니다.

자기 자신으로 가는 간선이 있으면 크기가 1이어도 순환입니다. 그렇지 않으면 순환이 아닙니다. 순환 의존을 찾는 것이 목적이라면 이 자기 순환을 빠뜨리면 안 됩니다. 모듈이 자기를 import 하는 일은 드물지만 빌드 규칙이나 상태 기계에서는 흔합니다.

그쪽은 방향을 무시했을 때의 연결 요소입니다. A → B만 있고 되돌아오는 길이 없으면 방향을 무시하면 한 덩어리이지만, 강한 연결 요소로는 둘로 갈립니다. 순환 의존을 찾을 때 필요한 것은 방향을 지키는 이쪽입니다.

전송되지 않습니다. 모든 계산은 브라우저 안에서 이뤄지고, 입력값은 이 기기에만 남습니다.

알아두면 좋은 점

  • 검증은 코사라주 알고리즘을 정답지로 삼아 했습니다. 무작위 방향 그래프 400벌(정점 3~10개, 자기 순환 포함)에서 두 알고리즘이 같은 묶음을 내는 것을 확인했습니다. 원 그래프의 끝난 순서를 쌓고 간선을 뒤집어 훑는 아예 다른 방법이라 서로를 검산해 줍니다.
  • 묶음 번호가 축약 그래프의 위상 순서라는 것을 무작위 300벌에서 고정했습니다. 모든 축약 간선이 번호가 커지는 쪽으로만 가는지 확인하는 방식입니다.
  • 같은 묶음에 든 정점끼리는 실제로 양방향으로 닿고, 다른 묶음이면 양방향으로는 닿지 않는다는 것을 도달 가능성을 직접 훑어 대조했습니다. 강한 연결 요소의 정의 그 자체를 확인하는 테스트입니다.
  • 자기 순환이 있는 크기 1 묶음을 순환으로 세는 것, 없는 경우는 순환이 아닌 것을 따로 고정했습니다.
  • 정점은 26개까지 다룹니다. 표와 묶음 목록을 함께 보이는 것이 목적이라 그보다 크면 화면이 읽히지 않습니다.
  • 간선 입력은 위상 정렬 계산기와 같은 형식을 씁니다. 「A -> B」, 「A B」, 「A, B」 모두 읽고 한 줄에 「A B C」가 오면 A→B, B→C로 읽습니다.

함께 보면 좋은 도구

마지막 검증: 2026년 9월 1일 · 결과는 참고용 추정치입니다.