Algorithm🌊/정리

μœ λ‹ˆμ˜¨-νŒŒμΈλ“œ(Union-Find)

μ–΄μ œμ‹œμž‘ 2024. 12. 23. 10:20

ν•΄λ‹Ή 글은 μ €μž, 본인이 μ΄ν•΄ν•˜κΈ° μœ„ν•΄μ„œ μ“΄ κΈ€μž„μ„ λ°νž™λ‹ˆλ‹€. (κ³΅λΆ€ν•˜μž!)

μ„œλ‘œμ†Œ μ§‘ν•©(Disjoint Set)


Disjoint Set(μ„œλ‘œμ†Œ μ§‘ν•©, 뢄리 μ§‘ν•©)μ΄λž€ μ„œλ‘œ κ³΅ν†΅λœ μ›μ†Œλ₯Ό κ°€μ§€κ³  μžˆμ§€ μ•Šμ€ 두 개 μ΄μƒμ˜ 집합을 λ§ν•©λ‹ˆλ‹€.(였!)

 

μœ λ‹ˆμ˜¨-νŒŒμΈλ“œ(Union-Find)


μœ λ‹ˆμ˜¨-νŒŒμΈλ“œ μ•Œκ³ λ¦¬μ¦˜μ€ ν•©μ§‘ν•© ν•˜κ³  ν•΄λ‹Ή μš”μ†Œκ°€ μ†Œμ†λœ 집합을 μ°Ύμ•„λ‚΄λŠ”(Find) ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜μ΄λ‹€.

μ„œλ‘œμ†Œ μ§‘ν•© μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œλ„ 뢈리며, λ…Έλ“œ κ°„μ˜ μ—°κ²° 관계λ₯Ό μ‚¬μš©ν•˜λŠ” λ“±μœΌλ‘œ 자주 μ‚¬μš©λœλ‹€.

1. κΈ°λ³Έ μ—°μ‚°

  • Union μ—°μ‚° : 두 개의 집합을 ν•˜λ‚˜μ˜ μ§‘ν•©μœΌλ‘œ ν•©μΉ˜λŠ” μ—°μ‚°μž…λ‹ˆλ‹€. 즉, ν•œ 트리의 루트λ₯Ό λ‹€λ₯Έ 트리의 λ£¨νŠΈμ— μ—°κ²°ν•˜μ—¬ 두 트리λ₯Ό ν•˜λ‚˜λ‘œ κ²°ν•©ν•©λ‹ˆλ‹€.
    1. find 연산을 톡해 두 μš”μ†Œμ˜ 루트 λ…Έλ“œλ₯Ό 찾음.
    2. 두 루트 λ…Έλ“œμ€‘ ν•˜λ‚˜λ₯Ό λ‹€λ₯Έ 트리의 루트 λ…Έλ“œ μ•„λž˜μ— λ°°μΉ˜ν•˜μ—¬ 두 트리λ₯Ό ν•©μΉ¨.
    • 주의점!
      • μ„ ν˜• νŠΈλ¦¬κ°€ μƒκΈΈμˆ˜ μžˆλ‹€.
      • Find 연산이 O(N)이 걸리게 λœλ‹€.
  • Find μ—°μ‚° : μ–΄λ–€ μ›μ†Œκ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ 이 μ›μ†Œκ°€ μ†ν•œ μ§‘ν•©μ˜ λŒ€ν‘œ μ›μ†Œ(=루트 λ…Έλ“œ)λ₯Ό λ°˜ν™˜ν•˜λŠ” μ—°μ‚°μž…λ‹ˆλ‹€ 이 연산은 λŒ€ν‘œ μ›μ†Œμ— 도달할 λ•ŒκΉŒμ§€ λΆ€λͺ¨ 배열을 μž¬κ·€μ μœΌλ‘œ μˆœνšŒν•©λ‹ˆλ‹€.

2. μš©λ„.

μ§‘ν•© μ†Œμ† μ—¬λΆ€ νŒλ‹¨. : μž„μ˜μ˜ 두 λ…Έλ“œκ°€ λ™μΌν•œ 집합에 속해 μžˆλŠ”μ§€λ₯Ό 확인할 수 μžˆλ‹€. κ·Έλž˜ν”„ 라면 μž„μ˜μ˜ 두 λ…Έλ“œκ°€ μ—°κ²°λ˜μ–΄ μžˆλŠ”μ§€λ₯Ό νŒλ‹¨ν•  수 μžˆλ‹€.

경둜 μ••μΆ•: Find 연산쀑 μ••μΆ• 기법을 μ‚¬μš©ν•˜μ—¬, κ·Έλž˜ν”„ λ‚΄μ—μ„œ λ…Έλ“œκ°„μ˜ 경둜λ₯Ό μ΅œμ ν™”ν•  수 μžˆλ‹€. → μ‹œκ°„λ³΅μž‘λ„λ₯Ό ν–₯상할 수 μžˆλ‹€.

사이클 감지 : κ·Έλž˜ν”„ 탐색 쀑에 μƒˆλ‘œμš΄ μ—°κ²°(Edge)이 사이클을 λ§Œλ“œλŠ”μ§€ 감지할 수 μžˆλ‹€.

  • κ·ΈλŸ¬λ‚˜, 무방ν–₯ κ·Έλž˜ν”„μ—μ„œλ§Œ 적용 κ°€λŠ₯

3. κ³Όμ •

- 1 Union μ—°μ‚°

μ—¬λŸ¬ λ…Έλ“œ 쀑 두 λ…Έλ“œλ₯Ό μ„ νƒν•˜μ—¬ ν•˜λ‚˜μ˜ μ§‘ν•©μœΌλ‘œ μ—°κ²° ν•˜λ €κ³  ν•œλ‹€!

1차원 λ°°μ—΄μ˜ λŒ€ν‘œ λ…Έλ“œλ₯Ό κ°±μ‹ ν•΄μ£Όμ–΄ ν•˜λ‚˜μ˜ μ§‘ν•©μœΌλ‘œ λ¬ΆλŠ” 과정이닀.

*μœ μ˜ν•  점! : Union μ—°μ‚° μ‹œ 항상 λŒ€ν‘œ λ…Έλ“œλΌλ¦¬λ₯Ό μ—°κ²°ν•΄μ£Όμ–΄μ•Ό ν•œλ‹€.

  1. μ—°κ²°ν•  두 λ…Έλ“œλ₯Ό μž…λ ₯으둜 λ°›λŠ”λ‹€.
  2. 두 λ…Έλ“œμ˜ λŒ€ν‘œ λ…Έλ“œλ₯Ό find()λ₯Ό 톡해 μ°ΎλŠ”λ‹€.
  3. λŒ€ν‘œ λ…Έλ“œλΌλ¦¬ union을 μ§„ν–‰ν•œλ‹€.

static void union(int x, int y) {
        int a = find(x);
        int b = find(y);
        if(a > b){
            parents[b] = a;
        }
        else{
            parents[a] = b;
        }
    }

-2 Find μ—°μ‚°

νŠΉμ • λ…Έλ“œμ˜ λŒ€ν‘œ λ…Έλ“œλ₯Ό μ°Ύμ•„λ‚΄κ³ , λŒ€ν‘œ λ…Έλ“œκ°€ κ°™μœΌλ©΄ ν•΄λ‹Ή λ…Έλ“œλ“€μ΄ 같은 집합에 속해 μžˆλŠ”μ§€λ₯Ό 확인할 수 μžˆλ‹€. 이 연산은 λŒ€ν‘œ μ›μ†Œμ— 도달할 λ•ŒκΉŒμ§€ λΆ€λͺ¨ 배열을 μž¬κ·€μ μœΌλ‘œ μˆœνšŒν•©λ‹ˆλ‹€.

 

초기의 find 연산은 자기 μžμ‹ μ„ 가리킨닀.

 

λ³‘ν•©λœ 집합이 μžˆλ‹€λ©΄ κ·Έ μ§‘ν•©μ˜ λŒ€ν‘œ λ…Έλ“œλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.

static int find(int x) {
			if (parents[x] == x) return x;
			return parents[x] = find(parents[x]); // 경둜 μ••μΆ•
	}