πŸ“ˆ μ„œλ‘œμ†Œ 집합(Disjoint Sets)

  • μ„œλ‘œμ†Œ λΆ€λΆ„ μ§‘ν•©λ“€λ‘œ λ‚˜λˆ„μ–΄μ§„ μ›μ†Œλ“€μ˜ 데이터λ₯Ό μ²˜λ¦¬ν•˜κΈ° μœ„ν•œ 자료ꡬ쑰
  • μ„œλ‘œμ†Œ 집합 정보(합집합 μ–Έμ‚°)κ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ 트리 자료 ꡬ쑰λ₯Ό μ΄μš©ν•΄ 집합을 ν‘œν˜„ν•¨
  • union(합집합) : 연산을 ν™•μΈν•˜λ©°, μ„œλ‘œ μ—°κ²°λœ 두 λ…Έλ“œ 확인
## μ„œλ‘œμ†Œμ§‘ν•©
def union_parent(parent, a, b):
    a = find_parent(parent, a)
    b = find_parent(parent, b)
    if a < b:
      parent[b] = a
    else:
      parent[a] = b

## νŠΉμ • μ›μ†Œκ°€ μ†ν•œ 집합 μ°ΎκΈ°
def find_parent(parent, x):
    # λ§Œμ•½ μ΄ˆκΈ°ν™”ν•΄λ†¨λ˜ λ‹€λ₯΄λ‹€λ©΄
    # => 루트 λ…Έλ“œκ°€ μ•„λ‹ˆλΌλ©΄ 루트 λ…Έλ“œλ₯Ό μ°Ύμ„λ•ŒκΉŒμ§€ μž¬κ·€ 호좜
    if parent[x] != x:
        return find_parent(parent, parent[x])
    return x

## 경둜 단좕 μ‚¬μš©
def find_parent(parent, x):
    # λ§Œμ•½ μ΄ˆκΈ°ν™”ν•΄λ†¨λ˜ λ‹€λ₯΄λ‹€λ©΄
    # => 루트 λ…Έλ“œκ°€ μ•„λ‹ˆλΌλ©΄ 루트 λ…Έλ“œλ₯Ό μ°Ύμ„λ•ŒκΉŒμ§€ μž¬κ·€ 호좜
    if parent[x] != x:
        parent[x] = find_parent(parent, parent[x])
    return parent[x]

v, e = map(int, input().split())
parent = [i for i in range(v+1)]

for i in range(e):
    a, b = map(int, input().split())
    union_parent(parent, a, b)

print("각 μ›μ†Œκ°€ μ†ν•œ 집합 : ", end="")
for i in range(1, v+1):
  print(find_parent(parent, i), end=" ")

print()

print("λΆ€λͺ¨ ν…Œμ΄λΈ”  : ", end="")
for i in range(1, v+1):
    print(parent[i], end=' ')

πŸ“ˆ 경둜 함좕을 μ‚¬μš©ν•œ μ„œλ‘œμ†Œ 집합 μ•Œκ³ λ¦¬μ¦˜

## μ„œλ‘œμ†Œμ§‘ν•©
def union_parent(parent, a, b):
    a = find_parent(parent, a)
    b = find_parent(parent, b)
    if a < b:
        parent[b] = a
    else:
        parent[a] = b

## 경둜 단좕 μ‚¬μš©
def find_parent(parent, x):
    # λ§Œμ•½ μ΄ˆκΈ°ν™”ν•΄λ†¨λ˜ λ‹€λ₯΄λ‹€λ©΄
    # => 루트 λ…Έλ“œκ°€ μ•„λ‹ˆλΌλ©΄ 루트 λ…Έλ“œλ₯Ό μ°Ύμ„λ•ŒκΉŒμ§€ μž¬κ·€ 호좜
    if parent[x] != x:
        parent[x] = find_parent(parent, parent[x])
    return parent[x]

v, e = map(int, input().split())
parent = [i for i in range(v+1)]

for i in range(e):
    a, b = map(int, input().split())
    union_parent(parent, a, b)

print("각 μ›μ†Œκ°€ μ†ν•œ 집합 : ", end="")
for i in range(1, v+1):
    print(find_parent(parent, i), end=" ")

print()

print("λΆ€λͺ¨ ν…Œμ΄λΈ”  : ", end="")
for i in range(1, v+1):
    print(parent[i], end=' ')

πŸ“ˆμ‚¬μ΄ν΄ νŒλ³„ μ•Œκ³ λ¦¬μ¦˜

def find_parent(parent, x):
  if parent[x] != x:
    return find_parent(parent, parent[x])
  else:
    return parent[x]

def union_parent(parent, a, b):
  a = find_parent(parent, a)
  b = find_parent(parent, b)
  if a < b:
    parent[b] = a
  else:
    parent[a] = b

v, e = map(int, input().split())
parent = [0] * (v+1)

for i in range(1, v+1):
  parent[i] = i

cycle = False
for i in range(e):
  a, b = map(int, input().split())
  if find_parent(parent, a) == find_parent(parent, b):
    cycle = True
    break
  else:
    union_parent(parent, a, b)
  if cycle:
    print("사이클 λ°œμƒ")
  else:
    print("사이클 λ…Έλ°œμƒ")

πŸ“ˆ μ‹ μž₯ 트리

  • ν•˜λ‚˜μ˜ κ·Έλž˜ν”„κ°€ μžˆμ„ λ•Œ λͺ¨λ“  λ…Έλ“œλ₯Ό ν¬ν•¨ν•˜λ©΄μ„œ 사이클이 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” λΆ€λΆ„ κ·Έλž˜ν”„

πŸ“ˆ 크루슀칼 μ•Œκ³ λ¦¬μ¦˜

  • μ΅œμ†Œ μ‹ μž₯트리 μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ κ°€μž₯ 적은 λΉ„μš©μœΌλ‘œ λͺ¨λ“  λ…Έλ“œλ₯Ό μ—°κ²°ν•˜λŠ” κ·Έλž˜ν”„ μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ λΆ„λ₯˜λœλ‹€.
  • ꡬ체적인 μ•Œκ³ λ¦¬μ¦˜μ€ μ•„λž˜μ™€ κ°™λ‹€.
    1. κ°„μ„  데이텅λ₯Ό λΉ„μš©μ— 따라 μ˜€λ¦„μ°¨μˆœμœΌλ‘œ μ •λ ¬ν•œλ‹€.
    2. 간선을 ν•˜λ‚˜μ”© ν™•μΈν•˜μ—¬ ν˜„μž¬μ˜ 간선이 사이클을 λ°œμƒμ‹œν‚€λŠ”μ§€ ν™•μΈν•œλ‹€.
    3. λ§Œμ•½ 사이클이 λ°œμƒν•˜λŠ” 경우 μ΅œμ†Œ μ‹ μž₯ νŠΈλ¦¬μ— ν¬ν•¨μ‹œν‚¨λ‹€.
    4. 사이클이 λ°œμƒν•˜μ§€ μ•ŠλŠ” 경우 μ΅œμ†Œ μ‹ μž₯ νŠΈλ¦¬μ— ν¬ν•¨μ‹œν‚€μ§€ μ•ŠλŠ”λ‹€.
    5. λͺ¨λ“  간선에 λŒ€ν•΄ μœ„μ˜ 과정을 λ°˜λ³΅ν•œλ‹€.
  • 크루슀칼 μ•Œκ³ λ¦¬μ¦˜ μ‹œκ°„ λ³΅μž‘λ„ : O(ElogE)
def find_parent(parent, x):
    if parent[x] != x:
        return find_parent(parent, parent[x])
    else:
        return parent[x]
    
def union_parent(parent, a, b):
    a = find_parent(parent, a)
    b = find_parent(parent, b)
    if a<b:
        parent[b] = a
    else:
        parent[a] = b

v, e = map(int, input().split())
parent = [0]*(v+1)
edges = []
result = 0

for i in range(1, v+1):
    parent[i] = i

for i in range(e):
    a, b, cost = map(int, input().split())
    edges.append((cost,a,b))

edges.sort()

for edge in edges:
    cost, a, b = edge
    if find_parent(parent, a) != find_parent(parent, b):
        union_parent(parent, a, b)
        result += cost

print(result)

πŸ“ˆ μœ„μƒ μ •λ ¬

  • λ°©ν–₯ κ·Έλž˜ν”„μ˜ λͺ¨λ“  λ…Έλ“œλ₯Ό β€˜λ°©ν–₯성에 거슀λ₯΄μ§€ μ•Šλ„λ‘ μˆœμ„œλŒ€λ‘œ λ‚˜μ—΄ν•˜λŠ” 것
  • μˆœμ„œκ°€ μ •ν•΄μ Έ μžˆλŠ” 일련의 μž‘μ—…μ„ μ°¨λ‘€λ‘œ μˆ˜ν–‰ν•΄μ•Ό ν•  λ•Œ μ‚¬μš©ν•œλ‹€.
  • μ§„μž…μ°¨μˆ˜ : νŠΉμ •ν•œ λ…Έλ“œλ‘œ λ“€μ–΄μ˜€λŠ” κ°„μ„ μ˜ 개수
  • μœ„μƒ μ •λ ¬ μ•Œκ³ λ¦¬μ¦˜
    • μ§„μž…μ°¨μˆ˜κ°€ 0인 λ…Έλ“œλ₯Ό 큐에 λ„£λŠ”λ‹€.
    • νμ—μ„œ μ›μ†Œλ₯Ό κΊΌλ‚΄ ν•΄λ‹Ή λ…Έλ“œμ—μ„œ μΆ”μž˜ν•˜λŠ” 간선을 κ·Έλž˜ν”„μ—μ„œ μ œκ±°ν•œλ‹€.
    • μƒˆλ‘­κ²Œ μ§„μž…μ°¨μˆ˜κ°€ 0이 된 λ…Έλ“œλ₯Ό 큐에 λ„£λŠ”λ‹€
    • 큐가 λΉŒλ•ŒκΉŒμ§€ λ°˜λ³΅ν•œλ‹€.
  • μœ„μƒμ •λ ¬ μ‹œκ°„λ³΅μž‘λ„ : O(ElogE)
from collections import deque

# λ…Έλ“œμ˜ κ°œμˆ˜μ™€ κ°„μ„ μ˜ 개수 μž…λ ₯λ°›κΈ°
v, e = map(int, input().split())
# λͺ¨λ“  λ…Έλ“œμ— λŒ€ν•œ μ§„μž…μ°¨μˆ˜λŠ” 0으둜 μ΄ˆκΈ°ν™”
indegree = [0] * (v+1)
# 각 λ…Έλ“œμ— μ—°κ²°λœ κ°„μ„  정보λ₯Ό λ‹΄κΈ° μœ„ν•œ μ—°κ²° 리슀트(κ·Έλž˜ν”„) μ΄ˆκΈ°ν™”
graph =[[] for i in range(v+1)]

for i in range(e):
  a, b = map(int, input().split())
  graph[a].append(b) # 정점 aμ—μ„œ b둜 이동 κ°€λŠ₯
  indegree[b] += 1 # b의 μ§„μž…μ°¨μˆ˜ 1 증가

def topology_sort():
  result = []
  q = deque()

  for i in range(1, v+1):
    if indegree[i] == 0:
      q.append(i)
  # 큐가 λΉŒλ•ŒκΉŒμ§€ 반볡
  while q:
    # νμ—μ„œ μ›μ†Œ κΊΌλ‚΄κΈ°
    now = q.popleft()
    result.append(now)
    for i in graph[now]:
      indegree[i] -= 1
      if indegree[i] == 0:
        q.append(i)

  for i in result:
    print(i, end=' ')

topology_sort()
profile
μ΄μ‚¬μ€‘μž…λ‹ˆλ‹€!🌟https://velog.io/@devkyoung2

0개의 λŒ“κΈ€