코딩테스트/python

[programmers/python] 네트워크 개수 구하기 – Union-Find

zyin 2025. 5. 26. 10:00

문제 설명

- url : https://school.programmers.co.kr/learn/courses/30/lessons/43162

네트워크란 컴퓨터들 간에 정보 교환이 가능한 연결 상태를 의미한다.
예를 들어, 컴퓨터 A와 B가 연결되어 있고, B와 C도 연결되어 있다면 A와 C는 간접적으로 연결되어 있다고 본다.
이러한 경우 세 컴퓨터는 하나의 네트워크에 속한다고 판단한다.


입력 및 목표

  • n: 컴퓨터의 수 (1 ≤ n ≤ 200)
  • computers: n x n 크기의 2차원 배열로, computers[i][j] = 1이면 i번과 j번 컴퓨터가 연결되어 있음을 의미한다.
  • computers[i][i] = 1은 항상 성립한다.
  • 목표는 전체 컴퓨터를 연결 관계에 따라 그룹화하고, 총 네트워크의 개수를 구하는 것이다.

해결 전략

이 문제는 그래프에서 연결된 집합의 수를 묻는 전형적인 문제이다.
DFS나 BFS로 해결할 수도 있지만, Union-Find (서로소 집합) 알고리즘을 이용하면 더 직관적으로 해결할 수 있다.

Union-Find는 각 노드(컴퓨터)의 대표 루트를 추적하여, 연결된 노드끼리는 하나의 집합으로 병합하는 구조이다.
최종적으로는 각 노드의 루트를 기준으로 중복을 제거하면 전체 네트워크 수를 구할 수 있다.


구현

import sys
sys.setrecursionlimit(1000000)

def solution(n, computers):
    parents = [i for i in range(n)]  # 자기 자신이 부모이다.

    def find(a):
        if parents[a] != a:
            parents[a] = find(parents[a])  # 경로 압축을 적용한다.
        return parents[a]

    def union(a, b):
        pa = find(a)
        pb = find(b)
        if pa != pb:
            parents[pb] = pa  # 두 집합을 병합한다.

    for i in range(n):
        for j in range(n):
            if computers[i][j] == 1 and i != j:
                union(i, j)  # 연결된 노드들을 하나의 집합으로 병합한다.

    # 모든 노드의 루트를 찾아 중복을 제거하고, 그 수를 반환한다.
    return len(set(find(i) for i in range(n)))

동작 예시

print(solution(3, [[1,1,0], [1,1,0], [0,0,1]]))  # 출력: 2
print(solution(3, [[1,1,0], [1,1,1], [0,1,1]]))  # 출력: 1
  • 첫 번째 예제에서는 0번과 1번이 연결되어 하나의 네트워크를 이루고, 2번은 따로 떨어져 있으므로 총 2개의 네트워크가 존재한다.
  • 두 번째 예제에서는 0번, 1번, 2번이 모두 연결되어 있으므로 하나의 네트워크만 존재한다.

시간 복잡도

  • 모든 노드 쌍을 확인하는 반복문은 O(n²)이다.
  • Union-Find 연산은 경로 압축을 통해 거의 O(1)에 수렴하므로 전체적으로 O(n²)의 시간 복잡도를 갖는다.
  • n이 최대 200이므로 충분히 빠르게 실행 가능하다.