
✔️ gold 4
자료 구조
그래프 이론
그래프 탐색
분리 집합
노드(사람)들 사이에 "파티"라는 연결점이 있다는 부분에서 최근에 풀었던 환승(boj_5214)의 하이퍼튜브가 생각났다. 이 문제에서도 역들을 잇는 하이퍼튜브들이 주어지는데, 이를 가상의 노드로 보고 거쳐가도록 그래프를 구성했었다. 이 문제에서도 같은 아이디어를 적용했다.
그래프에서 1번 부터 n번 까지는 사람들, n+1번 부터 n+m번 까지는 파티로 놓고 파티와 사람들을 연결하도록 했다.
그리고 BFS를 통해 탐색을 진행하는데 파티가 탐색될 때마다 그 수를 res에 카운트하고 최종적으로 전체 파티의 수에서 탐색된 파티(진실을 아는 사람들이 참석한 파티)를 뺀 뒤 리턴한다.
나는 현재 그래프 문제집을 풀고있기 때문에 당연히 그래프를 이용해 푸는 문제라고 생각했다.
물론 그래프 문제도 맞고 내가 푼 풀이도 정답을 받았지만, 막상 받고 알고리즘 분류를 확인해보니 분리 집합이라는 게 있었다. 처음보는 유형이었다!
ChatGPT를 이용해서 간단하게 분리 집합에 대해서 알아보고 그 내용을 정리했다.
정의
서로 겹치지 않는 여러 개의 집합을 효율적으로 관리하는 자료구조
그래프 이론에서 서로 연결되어 있는 요소들을 그룹화할 때 유용
대표적으로 최소 신장 트리를 구하는 크루스칼(Kruskal) 알고리즘에서 사용
주요 연산
Find(찾기)Union(합집합)최적화 기법
➡️ Find 연산 속도 향상
시간 복잡도 (n = 노드의 수)
findunion# 거짓말
# graph
import sys
from collections import deque
input = sys.stdin.readline
def bfs(g: list, s: list, n: int, m: int):
vst = [0 for node in range(len(g))]
res = 0
for sx in s:
q = deque([sx])
vst[sx] = 1
while q:
x = q.popleft()
for nx in g[x]:
if vst[nx]:
continue
q.append(nx)
vst[nx] = 1
if nx >= n+1:
res += 1
return m-res
if __name__ == "__main__":
n, m = map(int, input().split())
g = [[] for node in range(n + m + 1)]
t = list(map(int, input().split()))
t = t[1:]
for party in range(n+1, n+1+m):
people = list(map(int, input().split()))
people = people[1:]
for p in people:
g[p].append(party)
g[party].append(p)
result = bfs(g, t, n, m)
print(result)
분리 집합을 막상 정리하고나니 크루스칼 알고리즘에 대해 들으면서 아 여기 쓰이던게 이거구나 싶었다.
가볍게 봤지만 다시 정리하고 개념을 다지는 좋은 기회가 됐다.
크루스칼 알고리즘 정리할 때 다시 생각날 듯. 또 읽어보면 좋을 것 같다.
그리고 이번 코드가 유독 변수명을 잘 못지은 것 같다. 다른 코드라고 잘 지어줬던건 아니지만..
그리고!! 집합을 이용해서 푸신 분의 풀이도 링크를 올려본다.
확실히 훨씬 깔끔하고 논리적으로 이해도 더 쉬운 것 같다.