๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“š Computer Science/Algorithm

[์•Œ๊ณ ๋ฆฌ์ฆ˜] ๊ทธ๋ž˜ํ”„ ์•Œ๊ณ ๋ฆฌ์ฆ˜

by hyebin (Helia) 2022. 4. 14.
๋ฐ˜์‘ํ˜•

๊ทธ๋ž˜ํ”„(Graph)

  • ๋…ธ๋“œ(Node)์™€ ๋…ธ๋“œ ์‚ฌ์ด์— ์—ฐ๊ฒฐ๋œ ๊ฐ„์„ (Edge)์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์ž๋ฃŒ๊ตฌ์กฐ
  • ์„œ๋กœ ๋‹ค๋ฅธ ๊ฐœ์ฒด(ํ˜น์€ ๊ฐ์ฒด)(Object)๊ฐ€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋‹ค๋Š” ๋ฌธ์ œ๋Š” ๊ทธ๋ž˜ํ”„ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋– ์˜ฌ๋ฆฌ๊ธฐ
  • ๊ทธ๋ž˜ํ”„ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•
    1. ์ธ์ ‘ ํ–‰๋ ฌ(Adjacency Matrix) : 2์ฐจ์› ๋ฐฐ์—ด ์‚ฌ์šฉ
      • ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์ด ๋งŽ์ด ํ•„์š”ํ•˜์ง€๋งŒ ํŠน์ • ๋…ธ๋“œ ๊ฐ„ ๊ฐ„์„ ์˜ ๋น„์šฉ์„ O(1) ์‹œ๊ฐ„์œผ๋กœ ์ฆ‰์‹œ ์•Œ ์ˆ˜ ์žˆ์Œ
    2. ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ (Adjacency List) : ๋ฆฌ์ŠคํŠธ ์‚ฌ์šฉ
      • ๊ฐ„์„ ์˜ ๊ฐœ์ˆ˜์ธ O(E) ๋งŒํผ๋งŒ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์ด ํ•„์š”ํ•˜์ง€๋งŒ O(V) ์‹œ๊ฐ„ ์†Œ์š”
  1.  
  ๊ทธ๋ž˜ํ”„ ํŠธ๋ฆฌ
๋ฐฉํ–ฅ์„ฑ ๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„ ํ˜น์€ ๋ฌด๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„ ๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„
์ˆœํ™˜์„ฑ ์ˆœํ™˜ ๋ฐ ๋น„์ˆœํ™˜ ๋น„์ˆœํ™˜
๋ฃจํŠธ ๋…ธ๋“œ ์กด์žฌ ์—ฌ๋ถ€ ๋ฃจํŠธ ๋…ธ๋“œ๊ฐ€ ์—†์Œ ๋ฃจํŠธ ๋…ธ๋“œ๊ฐ€ ์กด์žฌ
๋…ธ๋“œ๊ฐ„ ๊ด€๊ณ„์„ฑ ๋ถ€๋ชจ์™€ ์ž์‹ ๊ด€๊ณ„ ์—†์Œ ๋ถ€๋ชจ ์ž์‹ ๊ด€๊ณ„
๋ชจ๋ธ์˜ ์ข…๋ฅ˜ ๋„คํŠธ์›Œํฌ ๋ชจ๋ธ ๊ณ„์ธต ๋ชจ๋ธ

 

์„œ๋กœ์†Œ ์ง‘ํ•ฉ(Disjoint Sets)

  • ๊ณตํ†ต ์›์†Œ๊ฐ€ ์—†๋Š” ๋‘ ์ง‘ํ•ฉ
  • ์„œ๋กœ์†Œ ์ง‘ํ•ฉ ์ž๋ฃŒ๊ตฌ์กฐ: ์„œ๋กœ์†Œ ๋ถ€๋ถ„ ์ง‘ํ•ฉ๋“ค๋กœ ๋‚˜๋ˆ„์–ด์ง„ ์›์†Œ๋“ค์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ž๋ฃŒ๊ตฌ์กฐ
  • ์„œ๋กœ์†Œ ์ง‘ํ•ฉ ์ž๋ฃŒ๊ตฌ์กฐ๋Š” union๊ณผ find 2๊ฐœ์˜ ์—ฐ์‚ฐ์œผ๋กœ ์ž‘ํ•  ์ˆ˜ ์žˆ์–ด union-find ์ž๋ฃŒ๊ตฌ์กฐ๋ผ๊ณ ๋„ ๋ถˆ๋ฆผ
    • union(ํ•ฉ์ง‘ํ•ฉ): 2๊ฐœ์˜ ์›์†Œ๊ฐ€ ํฌํ•จ๋œ ์ง‘ํ•ฉ์„ ํ•˜๋‚˜์˜ ์ง‘ํ•ฉ์œผ๋กœ ํ•ฉ์น˜๋Š” ์—ฐ์‚ฐ
    • find(์ฐพ๊ธฐ): ํŠน์ •ํ•œ ์›์†Œ๊ฐ€ ์†ํ•œ ์ง‘ํ•ฉ์ด ์–ด๋–ค ์ง‘ํ•ฉ์ธ์ง€ ์•Œ๋ ค์ฃผ๋Š” ์—ฐ์‚ฐ
  • ํŠธ๋ฆฌ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์ด์šฉํ•˜์—ฌ ์„œ๋กœ์†Œ ์ง‘ํ•ฉ์„ ๊ณ„์‚ฐํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘
    1. union ์—ฐ์‚ฐ์„ ํ™•์ธํ•˜์—ฌ ์„œ๋กœ ์—ฐ๊ฒฐ๋œ ๋‘ ๋…ธ๋“œ A, B๋ฅผ ํ™•์ธ
      1. A์™€ B์˜ ๋ฃจํŠธ ๋…ธ๋“œ A’์™€ B’๋ฅผ ์ฐพ์Œ
      2. A’๋ฅผ B’์˜ ๋ถ€๋ชจ ๋…ธ๋“œ๋กœ ์„ค์ • (B' → A')
    2. ๋ชจ๋“  union ์—ฐ์‚ฐ์„ ์ฒ˜๋ฆฌํ•  ๋•Œ๊นŒ์ง€ 1๋ฒˆ ๊ณผ์ • ๋ฐ˜๋ณต
  • ์„œ๋กœ์†Œ ์ง‘ํ•ฉ์€ ๋ฌด๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„์—์„œ ์‚ฌ์ดํด์„ ํŒ๋ณ„ํ•  ๋•Œ ์‚ฌ์šฉ
  • ๋ถ€๋ชจ ํ…Œ์ด๋ธ”์—๋Š” ๋ฃจํŠธ ๋…ธ๋“œ ๊ฐ’์ด ๋“ค์–ด๊ฐ€๊ธฐ ๋•Œ๋ฌธ์— ๋‘ ๋…ธ๋“œ์”ฉ ๋น„๊ตํ•˜๋ฉด์„œ ๋ฃจํŠธ ๋…ธ๋“œ๊ฐ€ ๊ฐ™๋‹ค๋ฉด ์‚ฌ์ดํด์ด ๋ฐœ์ƒํ•œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ
  • ์‹œ๊ฐ„ ๋ณต์žก๋„:  O(V+M(1+log(2-M/V) V))   <๋…ธ๋“œ์˜ ๊ฐœ์ˆ˜๊ฐ€ V๊ฐœ์ด๊ณ  ์ตœ๋Œ€ V-1๊ฐœ์˜ union ์—ฐ์‚ฐ๊ณผ M๊ฐœ์˜ find ์—ฐ์‚ฐ์ด ๊ฐ€๋Šฅํ•  ๋•Œ>

 

์‹ ์žฅ ํŠธ๋ฆฌ(Spanning Tree)

  • ํ•˜๋‚˜์˜ ๊ทธ๋ž˜ํ”„๊ฐ€ ์žˆ์„ ๋•Œ ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ํฌํ•จํ•˜๋ฉด์„œ ์‚ฌ์ดํด์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ถ€๋ถ„ ๊ทธ๋ž˜ํ”„

 

ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜(Kruskal Algorithm)

  • ์‹ ์žฅ ํŠธ๋ฆฌ ์ค‘ ์ตœ์†Œ ๋น„์šฉ์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์‹ ์žฅ ํŠธ๋ฆฌ๋ฅผ ์ฐพ๋Š” ๊ฒƒ์„ ์ตœ์†Œ ๋น„์šฉ ์‹ ์žฅ ํŠธ๋ฆฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋ผ๊ณ  ํ•˜๋ฉฐ, ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ๋Œ€ํ‘œ์ 
    1. ๊ฐ„์„  ๋ฐ์ดํ„ฐ๋ฅผ ๋น„์šฉ์— ๋”ฐ๋ผ ์˜ค๋ฆ„์ฐจ์ˆœ ์ •๋ ฌ
    2. ๊ฐ„์„ ์„ ํ•˜๋‚˜์”ฉ ํ™•์ธํ•˜๋ฉฐ ํ˜„์žฌ์˜ ๊ฐ„์„ ์ด ์‚ฌ์ดํด์„ ๋ฐœ์ƒ์‹œํ‚ค๋Š”์ง€ ํ™•์ธ
      1. ์‚ฌ์ดํด์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์ตœ์†Œ ์‹ ์žฅ ํŠธ๋ฆฌ์— ํฌํ•จ
      2. ์‚ฌ์ดํด์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ ์ตœ์†Œ ์‹ ์žฅ ํŠธ๋ฆฌ์— ๋ถˆํฌํ•จ
    3. ๋ชจ๋“  ๊ฐ„์„ ์— ๋Œ€ํ•˜์—ฌ 2๋ฒˆ ๊ณผ์ • ๋ฐ˜๋ณต
  • ๋ชจ๋“  ๊ฐ„์„ ์— ๋Œ€ํ•ด ์ •๋ ฌํ•œ ๋’ค ๊ฑฐ๋ฆฌ๊ฐ€ ์งง์€ ๊ฐ„์„ ๋ถ€ํ„ฐ ์ง‘ํ•ฉ์— ํฌํ•จ์‹œํ‚ค๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋ฆฌ๋”” ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ๋ถ„๋ฅ˜๋จ
  • ์‹œ๊ฐ„ ๋ณต์žก๋„: O(ElogE)   <E: ๊ฐ„์„ ์˜ ๊ฐœ์ˆ˜>   

 

์œ„์ƒ ์ •๋ ฌ(Topology Sort)

  • ์ˆœ์„œ๊ฐ€ ์ •ํ•ด์ ธ ์žˆ๋Š” ์ผ๋ จ์˜ ์ž‘์—…์„ ์ฐจ๋ก€๋Œ€๋กœ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜
  • ๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„์˜ ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ '๋ฐฉํ–ฅ์„ฑ์— ๊ฑฐ์Šค๋ฅด์ง€ ์•Š๋„๋ก ์ˆœ์„œ๋Œ€๋กœ ๋‚˜์—ดํ•˜๋Š” ๊ฒƒ'
  • ์œ„์ƒ ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์ง„์ž… ์ฐจ์ˆ˜๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋™์ž‘
    • ์ง„์ž… ์ฐจ์ˆ˜:
  • ์œ„์ƒ ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜
    1. ์ง„์ž… ์ฐจ์ˆ˜๊ฐ€ 0์ธ ๋…ธ๋“œ๋ฅผ ํ์— ๋„ฃ๋Š”๋‹ค
    2. ํ๊ฐ€ ๋นŒ๊นŒ์ง€ ๋‹ค์Œ์˜ ๊ณผ์ • ๋ฐ˜๋ณต
      1. ํ์—์„œ ์›์†Œ๋ฅผ ๊บผ๋‚ด ํ•ด๋‹น ๋…ธ๋“œ์—์„œ ์ถœ๋ฐœํ•˜๋Š” ๊ฐ„์„ ์„ ๊ทธ๋ž˜ํ”„์—์„œ ์ œ๊ฑฐ
      2. ์ƒˆ๋กญ๊ฒŒ ์ง„์ž… ์ฐจ์ˆ˜๊ฐ€ 0์ด ๋œ ๋…ธ๋“œ๋ฅผ ํ์— ๋„ฃ๋Š”๋‹ค
  • ์‹œ๊ฐ„ ๋ณต์žก๋„: O(V+E)

 


๊ทธ๋ž˜ํ”„ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ

ํŒ€ ๊ฒฐ์„ฑ

ํ•™๊ต์—์„œ ํ•™์ƒ๋“ค์—๊ฒŒ 0๋ฒˆ๋ถ€ํ„ฐ N๋ฒˆ๊นŒ์ง€์˜ ๋ฒˆํ˜ธ๋ฅผ ๋ถ€์—ฌํ–ˆ๋‹ค.
์ฒ˜์Œ์—๋Š” ๋ชจ๋“  ํ•™์ƒ์ด ์„œ๋กœ ๋‹ค๋ฅธ ํŒ€์œผ๋กœ ๊ตฌ๋ถ„๋˜์–ด, ์ด N+1๊ฐœ์˜ ํŒ€์ด ์กด์žฌํ•œ๋‹ค.
์ด๋•Œ, ์„ ์ƒ๋‹˜์€ 'ํŒ€ ํ•ฉ์น˜๊ธฐ' ์—ฐ์‚ฐ๊ณผ '๊ฐ™์€ ํŒ€ ์—ฌ๋ถ€ ํ™•์ธ' ์—ฐ์‚ฐ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

1. 'ํŒ€ ํ•ฉ์น˜๊ธฐ' ์—ฐ์‚ฐ์€ ๋‘ ํŒ€์„ ํ•ฉ์น˜๋Š” ์—ฐ์‚ฐ์ด๋‹ค.
2. '๊ฐ™์€ ํŒ€ ์—ฌ๋ถ€ ํ™•์ธ' ์—ฐ์‚ฐ์€ ํŠน์ •ํ•œ ๋‘ ํ•™์ƒ์ด ๊ฐ™์€ ํŒ€์— ์†ํ•˜๋Š”์ง€๋ฅผ ํ™•์ธํ•˜๋Š” ์—ฐ์‚ฐ์ด๋‹ค.

์„ ์ƒ๋‹˜์ด M๊ฐœ์˜ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์„ ๋•Œ, '๊ฐ™์€ ํŒ€ ์—ฌ๋ถ€ ํ™•์ธ' ์—ฐ์‚ฐ์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜์‹œ์˜ค.

'ํŒ€ ํ•ฉ์น˜๊ธฐ' ์—ฐ์‚ฐ์€ 0 a bํ˜•ํƒœ๋กœ ์ฃผ์–ด์ง€๋ฉฐ, '๊ฐ™์€ ํŒ€ ์—ฌ๋ถ€ ํ™•์ธ' ์—ฐ์‚ฐ์€ 1 a b ํ˜•ํƒœ๋กœ ์ฃผ์–ด์ง„๋‹ค.
//ํŠน์ • ์›์†Œ๊ฐ€ ์†ํ•œ ์ง‘ํ•ฉ ์ฐพ๊ธฐ
func find_parent(_ parent: [Int], _ x: Int) -> Int{
    var parent = parent
    if parent[x] != x{
        parent[x] = find_parent(parent, parent[x])
    }
    return parent[x]
}
//๋‘ ์›์†Œ๊ฐ€ ์†ํ•œ ์ง‘ํ•ฉ ํ•ฉ์น˜๊ธฐ
func union_parent(_ parent: [Int], _ a: Int, _ b: Int) -> [Int]{
    var new_a = find_parent(parent, a)
    var new_b = find_parent(parent, b)
    var new_parent = parent
    
    if new_a<new_b{
        new_parent[new_b] = new_a
    }else{
        new_parent[new_a] = new_b
    }
    return new_parent
}

var input_data = readLine()!.split(separator: " ").map{Int(String($0))!}
let n = input_data[0], m = input_data[1]

var parent: [Int] = Array(repeating: 0, count: n+1)
for i in 0...n{
    parent[i] = i
}

for i in 0..<m{
    input_data = readLine()!.split(separator: " ").map{Int(String($0))!}
    var oper = input_data[0], a = input_data[1], b = input_data[2]
    
    if oper == 0{
        parent = union_parent(parent, a, b)
    }
    else if oper == 1{
        find_parent(parent, a) == find_parent(parent, b) ? print("YES") : print("NO")
    }
}

๋„์‹œ ๋ถ„ํ•  ๊ณ„ํš

๋™๋ฌผ์›์—์„œ ๋ง‰ ํƒˆ์ถœํ•œ ์›์ˆญ์ด ํ•œ ๋งˆ๋ฆฌ๊ฐ€ ์„ธ์ƒ์„ ๊ตฌ๊ฒฝํ•˜๊ณ  ์žˆ๋‹ค.
์–ด๋А ๋‚  ์›์ˆญ์ด๋Š” 'ํ‰ํ™”๋กœ์šด ๋งˆ์„'์— ์ž ์‹œ ๋จธ๋ฌผ๋ €๋Š”๋ฐ, ๋งˆ์นจ ๋งˆ์„ ์‚ฌ๋žŒ๋“ค์€ ๋„๋กœ ๊ณต์‚ฌ ๋ฌธ์ œ๋กœ ํšŒ์˜ ์ค‘์ด์—ˆ๋‹ค.
๋งˆ์„์€ N๊ฐœ์˜ ์ง‘๊ณผ ๊ทธ ์ง‘๋“ค์„ ์—ฐ๊ฒฐํ•˜๋Š” M๊ฐœ์˜ ๊ธธ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค. ๊ธธ์€ ์–ด๋А ๋ฐฉํ–ฅ์œผ๋กœ๋“ ์ง€ ๋‹ค๋‹ ์ˆ˜ ์žˆ๋Š” ๊ธธ์ด๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๊ธธ๋งˆ๋‹ค ์œ ์ง€ํ•˜๋Š”๋ฐ ๋“œ๋Š” ์œ ์ง€๋น„๊ฐ€ ์žˆ๋‹ค.

๋งˆ์„์˜ ์ด์žฅ์€ ๋งˆ์„์„ 2๊ฐœ์˜ ๋ถ„๋ฆฌ๋œ ๋งˆ์„๋กœ ๋ถ„ํ• ํ•  ๊ณ„ํš์„ ์„ธ์šฐ๊ณ  ์žˆ๋‹ค. ๋งˆ์„์ด ๋„ˆ๋ฌด ์ปค์„œ ํ˜ผ์ž์„œ๋Š” ๊ด€๋ฆฌํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
๋งˆ์„์„ ๋ถ„ํ• ํ•  ๋•Œ๋Š” ๊ฐ ๋ถ„๋ฆฌ๋œ ๋งˆ์„ ์•ˆ์— ์ง‘๋“ค์ด ์„œ๋กœ ์—ฐ๊ฒฐ๋˜๋„๋ก ๋ถ„ํ• ํ•ด์•ผ ํ•œ๋‹ค. ๋งˆ์„์—๋Š” ์ง‘์ด ํ•˜๋‚˜ ์ด์ƒ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

์ผ๋‹จ ๋ถ„๋ฆฌ๋œ ๋‘ ๋งˆ์„ ์‚ฌ์ด์— ์žˆ๋Š” ๊ธธ๋“ค์€ ํ•„์š”์— ๋”ฐ๋ผ ์—†์•จ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ ๋ถ„๋ฆฌ๋œ ๋งˆ์„ ์•ˆ์—์„œ๋„ ์ž„์˜์˜ ๋‘ ์ง‘ ์‚ฌ์ด์— ๊ฒฝ๋กœ๊ฐ€ ํ•ญ์ƒ ์กด์žฌํ•˜๊ฒŒ ํ•˜๋ฉด์„œ ๊ธธ์„ ์—†์•จ ์ˆ˜ ์žˆ๋‹ค. ๋งˆ์„์˜ ์ด์žฅ์€ ์œ„ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋„๋ก ๊ธธ๋“ค์„ ์—†์• ๊ณ  ๋‚˜๋จธ์ง€ ๊ธธ์˜ ์œ ์ง€๋น„์˜ ํ•ฉ์œผ๋กœ ์ตœ์†Œ๋กœ ํ•˜๊ณ  ์‹ถ๋‹ค. ์ด๊ฒƒ์„ ๊ตฌํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜์‹œ์˜ค.

์ „์ฒด ๊ทธ๋ž˜ํ”„์—์„œ 2๊ฐœ์˜ ์ตœ์†Œ ์‹ ์žฅ ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค. ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ด์šฉํ•˜์—ฌ ์ตœ์†Œ ์‹ ์žฅ ํŠธ๋ฆฌ๋ฅผ ์ฐพ์€ ํ›„, ์ตœ์†Œ ์‹ ์žฅ ํŠธ๋ฆฌ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๊ฐ„์„  ์ค‘์—์„œ ๊ฐ€์žฅ ๋น„์šฉ์ด ํฐ ๊ฐ„์„ ์„ ์ œ๊ฑฐํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์ตœ์†Œ ์‹ ์žฅ ํŠธ๋ฆฌ๊ฐ€ 2๊ฐœ์˜ ๋ถ€๋ถ„ ๊ทธ๋ž˜ํ”„๋กœ ๋‚˜๋ˆ„์–ด์ง€๋ฉฐ, ์ตœ์ ์˜ ํ•ด๋ฅผ ๋งŒ์กฑํ•œ๋‹ค.

//ํŠน์ • ์›์†Œ๊ฐ€ ์†ํ•œ ์ง‘ํ•ฉ์„ ์ฐพ๊ธฐ
func find_parent(_ parent: [Int], _ x: Int) -> Int{
    var parent = parent
    if parent[x] != x{
        parent[x] = find_parent(parent, parent[x])
    }
    return parent[x]
}
//๋‘ ์›์†Œ๊ฐ€ ์†ํ•œ ์ง‘ํ•ฉ์„ ํ•ฉ์น˜๊ธฐ
func union_parent(_ parent: [Int], _ a: Int, _ b: Int) -> [Int]{
    var new_a = find_parent(parent, a)
    var new_b = find_parent(parent, b)
    var new_parent = parent
    
    if new_a<new_b{
        new_parent[new_b] = new_a
    }else{
        new_parent[new_a] = new_b
    }
    return new_parent
}

var input_data = readLine()!.split(separator: " ").map{Int(String($0))!}
let n = input_data[0], m = input_data[1]

var parent: [Int] = Array(repeating: 0, count: n+1)
for i in 0...n{
    parent[i] = i
}
//๋ชจ๋“  ๊ฐ„์„ ์„ ๋‹ด์„ ๋ฐฐ์—ด
var edges = [[Int]]()
//์ตœ์ข… ๋น„์šฉ์„ ๋‹ด์„ ๋ณ€์ˆ˜, ์ตœ์†Œ ์‹ ์žฅ ํŠธ๋ฆฌ์— ํฌํ•จ๋˜๋Š” ๊ฐ„์„  ์ค‘ ๋น„์šฉ์ด ๊ฐ€์žฅ ํฐ ๊ฐ„์„ 
var re: Int = 0, last = 0

for i in 0..<m{
    input_data = readLine()!.split(separator: " ").map{Int(String($0))!}
    var a = input_data[0], b = input_data[1], cost = input_data[2]
    edges.append([cost,a,b])
}

//
edges = edges.sorted{ $0[0] < $1[0] }

for edge in edges {
    var cost = edge[0], a = edge[1], b = edge[2]
    
    if find_parent(parent, a) != find_parent(parent, b){
        parent = union_parent(parent, a, b)
        re += cost
        last = cost
    }
}

print(re-last)

์ปค๋ฆฌํ˜๋Ÿผ

๋™๋นˆ์ด๋Š” ์˜จ๋ผ์ธ์œผ๋กœ ์ปดํ“จํ„ฐ๊ณตํ•™ ๊ฐ•์˜๋ฅผ ๋“ฃ๊ณ  ์žˆ๋‹ค. ์ด๋•Œ ๊ฐ ์˜จ๋ผ์ธ ๊ฐ•์˜๋Š” ์„ ์ˆ˜ ๊ฐ•์˜๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์„ ์ˆ˜ ๊ฐ•์˜๊ฐ€ ์žˆ๋Š” ๊ฐ•์˜๋Š” ์„ ์ˆ˜ ๊ฐ•์˜๋ฅผ ๋“ค์–ด์•ผ๋งŒ ํ•ด๋‹จ ๊ฐ•์˜๋ฅผ ๋“ค์„ ์ˆ˜ ์žˆ๋‹ค.
๋™๋นˆ์ด๋Š” ์ด N๊ฐœ์˜ ๊ฐ•์˜๋ฅผ ๋“ฃ๊ณ ์ž ํ•œ๋‹ค. ๋ชจ๋“  ๊ฐ•์˜๋Š” 1๋ฒˆ๋ถ€ํ„ฐ N๋ฒˆ๊นŒ์ง€์˜ ๋ฒˆํ˜ธ๋ฅผ ๊ฐ€์ง„๋‹ค. ๋˜ํ•œ ๋™์‹œ์— ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฐ•์˜๋ฅผ ๋“ค์„ ์ˆ˜ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค.
๋™๋นˆ์ด๊ฐ€ ๋“ฃ๊ณ ์ž ํ•˜๋Š” N๊ฐœ์˜ ๊ฐ•์˜ ์ •๋ณด๊ฐ€ ์ฃผ์–ด์กŒ์„ ๋•Œ, N๊ฐœ์˜ ๊ฐ•์˜์— ๋Œ€ํ•˜์—ฌ ์ˆ˜๊ฐ•ํ•˜๊ธฐ๊นŒ์ง€ ๊ฑธ๋ฆฌ๋Š” ์ตœ์†Œ ์‹œ๊ฐ„์„ ๊ฐ๊ฐ ์ถœ๋ ฅํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜์‹œ์˜ค.
์ž…๋ ฅ์€ ๊ฐ•์˜์˜ ์ˆ˜ N๊ณผ, ๊ฐ ๊ฐ•์˜์˜ ๊ฐ•์˜ ์‹œ๊ฐ„๊ณผ ๊ทธ ๊ฐ•์˜๋ฅผ ๋“ฃ๊ธฐ ์œ„ํ•ด ๋จผ์ € ๋“ค์–ด์•ผ ํ•˜๋Š” ๊ฐ•์˜๋“ค์˜ ๋ฒˆํ˜ธ๊ฐ€ ์ฃผ์–ด์ง€๋ฉฐ, ๊ฐ ์ค„์€ -1๋กœ ๋๋‚œ๋‹ค.
//ํ ๊ตฌํ˜„
public struct Queue<T> {
  fileprivate var array = [T]()

  public var isEmpty: Bool {
    return array.isEmpty
  }
  
  public var count: Int {
    return array.count
  }

  public mutating func enqueue(_ element: T) {
    array.append(element)
  }
  
  public mutating func dequeue() -> T? {
    if isEmpty {
      return nil
    } else {
      return array.removeFirst()
    }
  }
  
  public var front: T? {
    return array.first
  }
}
let n = Int(readLine()!)!
//๋ชจ๋“  ๋…ธ๋“œ์— ๋Œ€ํ•œ ์ง„์ž…์ฐจ์ˆ˜ 0์œผ๋กœ ์ดˆ๊ธฐํ™”
var indegree: [Int] = Array(repeating: 0, count: n+1)
//๊ฐ ๋…ธ๋“œ์— ์—ฐ๊ฒฐ๋œ ๊ฐ„์„  ์ •๋ณด๋ฅผ ๋‹ด๊ธฐ์œ„ํ•œ ๊ทธ๋ž˜ํ”„
var graph: [[Int]] = Array(repeating: Array(repeating: 0, count: 0), count: n+1)
//๊ฐ ๊ฐ•์˜ ์‹œ๊ฐ„
var time: [Int] = Array(repeating: 0, count: n+1)

//๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„์˜ ๋ณด๋“  ๊ฐ„์„  ์ •๋ณด ์ž…๋ ฅ๋ฐ›๊ธฐ
for i in 1...n{
    var data = readLine()!.split(separator: " ").map{Int(String($0))!}
    time[i] = data[0]
    for x in 1..<data.count-1{
        indegree[i] += 1
        graph[data[x]].append(i)
    }
}

//์œ„์‚ฐ ์ •๋ ฌ ํ•จ์ˆ˜
func topology_sort(){
    var result = time
    var q = Queue<Int>()
    
    //์ฒ˜์Œ ์‹œ์ž‘ํ•  ๋•Œ ์ง„์ž…์ฐจ์ˆ˜๊ฐ€ 0์ธ ๋…ธ๋“œ๋ฅผ ํ์— ์‚ฝ์ž…
    for i in 1...n{
        if indegree[i] == 0{
            q.enqueue(i)
        }
    }
    
    //ํ๊ฐ€ ๋นŒ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต
    while !q.isEmpty{
        var now = q.dequeue()!
        
        //ํ•ด๋‹จ ์›์†Œ์™€ ์—ฐ๊ฒฐ๋œ ๋…ธ๋“œ๋“ค์˜ ์ง‘์ž…์ฐจ์ˆ˜์—์„œ 1 ๋นผ๊ธฐ
        for i in graph[now]{
            result[i] = max(result[i], result[now]+time[i])
            indegree[i] -= 1
            if indegree[i] == 0{
                q.enqueue(i)
            }
        }
    }
    for i in 1...n{
        print(result[i])
    }
}
topology_sort()
๋ฐ˜์‘ํ˜•