1. ๋ถ„๋ฆฌ ์ง‘ํ•ฉ(Disjoint Set)

์„œ๋กœ์†Œ ์ง‘ํ•ฉ์ด๋ผ๊ณ  ๋ถˆ๋ฆฌ์šฐ๋Š” ๋ถ„๋ฆฌ ์ง‘ํ•ฉ์€ ์ค‘๋ณต๋˜๋Š” ๋ถ€๋ถ„์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ๋ชจ๋“  ์›์†Œ๋ฅผ ๋ถ„๋ฆฌํ•œ ์ง‘ํ•ฉ์„ ๋งํ•œ๋‹ค. ๊ทธ๋ƒฅ ์„œ๋กœ ์ค‘๋ณต๋˜์ง€ ์•Š๋Š” ๋ถ€๋ถ„ ์ง‘ํ•ฉ๋“ค๋กœ ์ด๋ฃจ์–ด์ง„ ์›์†Œ๋“ค์— ๋Œ€ํ•ด ์ €์žฅํ•˜๊ณ  ์žˆ๋Š” ์ž๋ฃŒ๊ตฌ์กฐ์ด๋‹ค.

  • ์ „์ฒด ์ง‘ํ•ฉ U์— ๋Œ€ํ•ด, U์˜ ๋ถ„๋ฆฌ ์ง‘ํ•ฉ A์™€ B๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์กฐ๊ฑด๋“ค์„ ๋งŒ์กฑํ•œ๋‹ค.
    • A, B๋Š” U์˜ ๋ถ€๋ถ„ ์ง‘ํ•ฉ์ด๋‹ค.
    • A, B๋Š” ๊ณตํ†ต ์›์†Œ๋ฅผ ๊ฐ€์ง€์ง€ ์•Š๋Š”๋‹ค.
    • A, B์˜ ํ•ฉ ์ง‘ํ•ฉ์ด ์ „์ฒด ์ง‘ํ•ฉ U์ด๋‹ค. (A, B ๋‘˜ ๋‹ค ์†ํ•˜์ง€ ์•Š๋Š” U์˜ ์›์†Œ๊ฐ€ ์—†์–ด์•ผ ํ•œ๋‹ค.)

 

2. ์œ ๋‹ˆ์˜จ ํŒŒ์ธ๋“œ(Union-Find)

์œ ๋‹ˆ์˜จ ํŒŒ์ธ๋“œ๋Š” ๋ถ„๋ฆฌ ์ง‘ํ•ฉ์„ ๊ตฌํ˜„ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ, ํŠธ๋ฆฌ ๊ตฌ์กฐ๋กœ ํ‘œํ˜„ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ํšจ์œจ์ ์ด(๋ผ๊ณ  ํ•œ)๋‹ค.

๋จผ์ €, ๊ฐ ๋…ธ๋“œ ๋ณ„๋กœ ๋ถ€๋ชจ ๋…ธ๋“œ ๋ฒˆํ˜ธ๋ฅผ ๊ธฐ๋กํ•œ๋‹ค. ๊ทธ๋Ÿผ ๊ทธ๋ž˜ํ”„๊ฐ€ ํŠธ๋ฆฌ ํ˜•ํƒœ๋กœ ํ‘œํ˜„๋œ๋‹ค.

  • ์ตœ์ƒ์œ„ ๋…ธ๋“œ์ธ root ๋…ธ๋“œ๋ผ๋ฉด ๋ถ€๋ชจ ๋…ธ๋“œ์˜ ๋ฒˆํ˜ธ๋Š” ์ž๊ธฐ ์ž์‹ ์˜ ๋ฒˆํ˜ธ์ด๋‹ค.
    • ์ด root ๋…ธ๋“œ๋กœ ๊ทธ๋ฃน์„ ๊ตฌ๋ณ„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๊ฐ ๋…ธ๋“œ๊ฐ€ ๊ฐ™์€ ๊ทธ๋ฃน์ธ์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์„ DFS ๋“ฑ์˜ ํƒ์ƒ‰์„ ๊ฑฐ์น˜์ง€ ์•Š๊ณ , ๋ถ€๋ชจ ๋…ธ๋“œ๊ฐ€ ์ผ์น˜ํ•˜๋Š”์ง€๋กœ ํŒ๋ณ„ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
  • ํ•œ ๋…ธ๋“œ์˜ ๊ทธ๋ฃน๊ณผ ๋‹ค๋ฅธ ํ•œ ๋…ธ๋“œ์˜ ๊ทธ๋ฃน์ด ํ•ฉ์ณ์ง„๋‹ค๋ฉด, ๋ถ€๋ชจ ๋…ธ๋“œ ๋ฒˆํ˜ธ๋ฅผ ๋‹ค๋ฅธ ํ•œ ๋…ธ๋“œ์˜ ๋ถ€๋ชจ ๋…ธ๋“œ๋กœ ์ง€์ •ํ•˜๋Š” ์‹์œผ๋กœ ํŠธ๋ฆฌ๋ฅผ ๋ณ‘ํ•ฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

(1) makeSet(x)

์ดˆ๊ธฐํ™” ์ž‘์—…. x๋ฅผ ์œ ์ผํ•œ ์›์†Œ๋กœ ํ•˜๋Š” ์ƒˆ๋กœ์šด ์ง‘ํ•ฉ์„ ๋งŒ๋“ ๋‹ค.

var parent = Array(0...n)
  • 0์—์„œ n๊นŒ์ง€์˜ ๋…ธ๋“œ์— ๋Œ€ํ•œ ๋ถ€๋ชจ ๋…ธ๋“œ ๋ฒˆํ˜ธ๋ฅผ ๊ธฐ๋กํ•œ ๋ฐฐ์—ด์„ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.

 

(2) find(x)

x๊ฐ€ ์†ํ•œ ์ง‘ํ•ฉ์˜ ๋Œ€ํ‘œ ๊ฐ’์ธ root ๋…ธ๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ฆ‰, x๊ฐ€ ์–ด๋–ค ์ง‘ํ•ฉ, ์–ด๋–ค ๊ทธ๋ฃน์—์— ์†ํ•ด ์žˆ๋Š”์ง€ ์ฐพ๋Š”๋‹ค.

func find(_ x: Int) -> Int {
    if x == parent[x] {
        return x // ๋ฃจํŠธ ๋…ธ๋“œ๋Š” ๋ถ€๋ชจ ๋…ธ๋“œ ๋ฒˆํ˜ธ๊ฐ€ ์ž๊ธฐ ์ž์‹ ์˜ ๋ฒˆํ˜ธ์ด๋‹ค. ๋”ฐ๋ผ์„œ ๋ฃจํŠธ ๋…ธ๋“œ์ด๋ฏ€๋กœ ๋ฆฌํ„ด
    } else {
        return parent[x] // ๋ถ€๋ชจ ๋…ธ๋“œ๋กœ ๊ฑฐ์Šฌ๋Ÿฌ ์˜ฌ๋ผ๊ฐ€๋Š” ์ค‘........
    }
}
  • ์žฌ๊ท€๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ถ€๋ชจ ๋…ธ๋“œ๋ฅผ ์ฐพ๋Š”๋‹ค.
  • ๋ถ€๋ชจ ๋…ธ๋“œ์˜ ๋ฒˆํ˜ธ๊ฐ€ ์ž๊ธฐ ์ž์‹ ์˜ ๋ฒˆํ˜ธ๋ผ๋ฉด ์—ฌ๊ธฐ๋Š” root ๋…ธ๋“œ์ž…๋‹ˆ๋‹ค..๋ฆฌํ„ดํ•œ๋‹ค.
  • ์žฌ๊ท€๋ฅผ ์ด์šฉํ•ด์„œ ๋ถ€๋ชจ ๋…ธ๋“œ๋กœ ๊ฑฐ์Šฌ๋Ÿฌ ์˜ฌ๋ผ๊ฐ„๋‹ค.

 

func find(_ x: Int) -> Int {
    if x != parent[x] {
		    parent[x] = find(parent[x])
    }
    
    return parent[x]
}
  • ๊ฒฝ๋กœ ์••์ถ•(Path Compression)์„ ํ†ตํ•œ ์ตœ์ ํ™” ์ฝ”๋“œ์ด๋‹ค.
  • ํ•˜๋‚˜์˜ ๋…ธ๋“œ์— ๋Œ€ํ•ด find ์—ฐ์‚ฐ์„ ํ•  ๋•Œ๋งˆ๋‹ค ๊ทธ ๋…ธ๋“œ์˜ ๋ถ€๋ชจ ๋…ธ๋“œ๋ฅผ ํ•ญ์ƒ root ๋…ธ๋“œ๋กœ ๋งŒ๋“ค์–ด์ค€๋‹ค๋ฉด, root ๋…ธ๋“œ๋ฅผ ์ฐพ์•„ ๊ฑฐ์Šฌ๋Ÿฌ ์˜ฌ๋ผ๊ฐˆ ํ•„์š”๊ฐ€ ์—†์–ด์ง„๋‹ค. find ์—ฐ์‚ฐ ์‹œ ์ค‘๋ณต๋˜๋Š” ์—ฐ์‚ฐ๋“ค์„ ์ค„์—ฌ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๋” ํšจ์œจ์ ์œผ๋กœ root ๋…ธ๋“œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ(๋‹ค๊ณ  ํ•œ)๋‹ค.

 

(3) union(x, y)

x๊ฐ€ ์†ํ•œ ์ง‘ํ•ฉ๊ณผ y๊ฐ€ ์†ํ•œ ์ง‘ํ•ฉ์„ ํ•ฉ์นœ๋‹ค. ์ฆ‰, ๋‘ ๊ฐœ์˜ ํŠธ๋ฆฌ๋ฅผ ๋ณ‘ํ•ฉํ•œ๋‹ค.

func union(_ x: Int, _ y: Int) {
    let rootX = find(x)
    let rootY = find(y)
    
    if rootX != rootY {
        parent[rootX] = rootY
    }
}
  • x, y ๊ฐ๊ฐ ์ตœ์ƒ์œ„ root ๋…ธ๋“œ rootX, rootY๋ฅผ find ์—ฐ์‚ฐ์„ ํ†ตํ•ด์„œ ์ฐพ๋Š”๋‹ค.
  • ๋งŒ์•ฝ root ๋…ธ๋“œ๊ฐ€ ๋‹ค๋ฅด๋‹ค๋ฉด, ์ด๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ํŠธ๋ฆฌ ๊ทธ๋ฃน์ด๋ฏ€๋กœ, ํ•œ ์ชฝ์˜ ํŠธ๋ฆฌ๋ฅผ ๋‹ค๋ฅธ ํ•œ ์ชฝ์— ๋ถ™์ธ๋‹ค. ํ•œ ์ชฝ์˜ root ๋…ธ๋“œ์˜ ๋ถ€๋ชจ ๋…ธ๋“œ๋ฅผ ๋‹ค๋ฅธ ํ•œ ์ชฝ์œผ๋กœ ๋“ฑ๋กํ•˜๋ฉด ๋œ๋‹ค.

 

var rank = [Int](repeating: 0, count: n + 1)

func union(_ x: Int, _ y: Int) {
    var rootX = find(x)
    var rootY = find(y)
    
    if rootX != rootY {
        if rank[rootX] < rank[rootY] {
            parent[rootX] = rootY // ๋†’์ด๊ฐ€ ๋‚ฎ์œผ๋ฉด(์ž‘์œผ๋ฉด) ๋†’์ด๊ฐ€ ๋†’์€ ๋ฐ์— ๋ถ™์ธ๋‹ค(๋ถ€๋ชจ ๋…ธ๋“œ๋กœ ๋“ฑ๋ก)
        } else rank[rootX] > rank[rootY] {
            parent[rootY] = rootX // ํŠธ๋ฆฌ์˜ ๋†’์ด๊ฐ€ ๋†’์€ ์ชฝ์ด ๋ฃจํŠธ๊ฐ€ ๋˜๋Š” ์…ˆ
        } else {
		        parent[rootX] = rootY // ๋†’์ด๊ฐ€ ๊ฐ™์œผ๋ฉด ์ผ๋‹จ x์˜ ๋ถ€๋ชจ๋ฅผ y๋กœ ์„ค์ •ํ•ด์„œ ํŠธ๋ฆฌ๋ฅผ ํ•ฉ์น˜๊ณ 
            rank[rootX] += 1 // ํ•ฉ์นœ ํŠธ๋ฆฌ์˜ ๋†’์ด 1 ์ฆ๊ฐ€
        }
    }
}
  • ํŠธ๋ฆฌ์˜ ๋†’์ด๋ฅผ ํ†ตํ•ด ์ตœ์ ํ™”ํ•œ ์ฝ”๋“œ์ด๋‹ค.
  • find์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” ํŠธ๋ฆฌ์˜ ๋†’์ด์— ์˜ํ•ด ๊ฒฐ์ •๋œ๋‹ค. ์ด๋•Œ, union ์—ฐ์‚ฐํ•  ๋•Œ ํ•ญ์ƒ ๋†’์ด๊ฐ€ ๋‚ฎ์€ ํŠธ๋ฆฌ๋ฅผ ๋†’์ด๊ฐ€ ๋†’์€ ํŠธ๋ฆฌ์— ๋ถ™์—ฌ์„œ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค. ๋†’์ด๊ฐ€ ๋‚ฎ์€ ํŠธ๋ฆฌ๋ฅผ ๋†’์€ ํŠธ๋ฆฌ์— ๋ถ™์—ฌ์•ผ ํ•ฉ์ณ์ง„ ํŠธ๋ฆฌ์˜ ๋†’์ด๊ฐ€ ๋œ ์ฆ๊ฐ€ํ•œ๋‹ค..
  • ๋”ฐ๋ผ์„œ ํŠธ๋ฆฌ์˜ ๋†’์ด๋ฅผ ๊ธฐ๋กํ•œ rank ๋ฐฐ์—ด์„ ๋ณ„๋„๋กœ ๋งŒ๋“ค์–ด๋†“๊ณ , ๋น„๊ตํ•˜๋ฉด์„œ

 

3. PS ๋ฌธ์ œ ๋ชฉ๋ก

 

4. ์ฐธ๊ณ  ์ž๋ฃŒ

user-img ๋“คํŒ์„์ง€๋‚˜๋Šช์ง€๋Œ€๋ฅผ๊ฑด๋„ˆ
kiln
ํ˜„์žฌ๊ธ€
[Swift/Algorithm] ๋ถ„๋ฆฌ ์ง‘ํ•ฉ(Disjoint Set)๊ณผ ์œ ๋‹ˆ์˜จ ํŒŒ์ธ๋“œ(Union-Find) ์•Œ๊ณ ๋ฆฌ์ฆ˜