프로그래머스 전력망을 둘로 나누기 풀이
n개의 송전탑이 전선을 통해 하나의 트리 형태로 연결되어 있습니다. 당신은 이 전선들 중 하나를 끊어서 현재의 전력망 네트워크를 2개로 분할하려고 합니다. 이때, 두 전력망이 갖게 되는 송전탑의 개수를 최대한 비슷하게 맞추고자 합니다.
송전탑의 개수 n, 그리고 전선 정보 wires가 매개변수로 주어집니다. 전선들 중 하나를 끊어서 송전탑 개수가 가능한 비슷하도록 두 전력망으로 나누었을 때, 두 전력망이 가지고 있는 송전탑 개수의 차이(절대값)를 return 하도록 solution 함수를 완성해주세요.
function solution(n, wires) {
// 결과에 최대로 나올수 있는 결과값을 미리 넣는다.
let result = n - 2;
// wires 배열을 돌면서 연결된 리스트들을 만들어 놓는다.
const wireMap = wires.reduce((acc, cur) => {
const [first, second] = cur;
acc.set(first, acc.get(first) ? [...acc.get(first), second] : [second]);
acc.set(second, acc.get(second) ? [...acc.get(second), first] : [first]);
return acc;
}, new Map());
// 전력망을 순회하면서 연결된 상황을 알려주는 dfs
const bfs = (wire, next) => {
// queue를 사용해서 배열 순회를 control한다.
const queue = [wire];
// 방문을 했는지 체크하는 visited배열을 만든다.
const visited = new Array(n).fill(false);
// 송전탑은 1부터 시작함으로 -1을 해준다.
visited[wire - 1] = true;
while(queue.length) {
// queue의 첫 번째를 빼준다.
const curWire = queue.shift();
wireMap.get(curWire).forEach(wire => {
// 이미 방문했거나, 끊은 전력망이면 전력망 queue에 넣지 않는다..
if (wire !== next && !visited[wire - 1]) {
visited[wire - 1] = true;
queue.push(wire);
}
});
}
// 순회에 성공한 송전탑 개수를 return 한다.
return visited.filter(visit => visit === true).length;
}
wires.forEach(([cur, next]) => {
// 지금까지의 최소 결과 값과 현재의 결과값을 비교한다.
// count - (n - count) = count * 2 - n이므로 다음과 같이 계산했다.
result = Math.min(result, Math.abs(bfs(cur, next) * 2 - n));
});
return result;
}