알고리즘 문제풀이
[프로그래머스] 전력망을 둘로 나누기 (Swift)
SiO2whocode
2025. 6. 16. 17:30
https://school.programmers.co.kr/learn/courses/30/lessons/86971?language=swift
DFS, 그래프
트리 모양의 그래프에서 간선을 하나 끊고 두 서브트리로 나눌 때,
이 두 서브트리의 노드 수의 차의 최솟값을 구하는 문제
접근방법
1. 양방향 그래프의 인접리스트를 생성 (서브트리 탐색 위함)
2. 모든 전선을 하나씩 끊어가면서, 각 경우에 대해 두 서브 트리의 노드 개수 차이 최솟값 갱신
2-1. 끊는 전선에 연결되어 있는 노드를 루트노드로 한 두 서브트리 중 하나의 서브트리 노드 개수 구하는 함수 선언 (getChildCnt - dfs)
- visit 배열을 inout으로 사용
- childCnt를 구하는 과정에서 초기값을 1로 해주어야 본인(서브트리의 루트노드)를 포함할 수 있음
시간 복잡도
- wires.count == n - 1 (트리 구조)
- 각 전선을 하나씩 제거 → O(n)
- 제거 후 DFS로 노드 수 계산 → O(n) (최악의 경우 전 노드 탐색)
전체 시간복잡도: O(n²) (n ≤ 100 → 충분히 가능)
소스코드
import Foundation
func solution(_ n:Int, _ wires:[[Int]]) -> Int {
// 양방향 그래프 인접리스트 생성
var adj:[[Int]] = [[Int]](repeating: [], count: n+1)
for wire in wires {
let a = wire[0]
let b = wire[1]
adj[a].append(b)
adj[b].append(a)
}
// 서브트리 노드 수 구하는 재귀 함수
func getChildCnt(_ parent:Int, _ visit: inout [Bool]) -> Int {
var childCnt:Int = 1 // 본인
for child in adj[parent] {
if !visit[child] {
visit[child] = true
childCnt += getChildCnt(child, &visit)
}
}
return childCnt
}
var result:Int = Int.max
// 전선 하나씩 끊어가면서 서브트리 노드 수 차이 최솟값 갱신
for wire in wires {
var visit:[Bool] = Array<Bool>(repeating: false, count: n+1)
visit[wire[0]] = true
visit[wire[1]] = true
var aTreeCnt:Int = getChildCnt(wire[0], &visit)
var bTreeCnt:Int = n-aTreeCnt
result = min(result, abs(aTreeCnt - bTreeCnt))
}
return result
}
728x90