프로그래머스 전력망을 둘로 나누기 - JS

김민찬·2023년 1월 7일
0

알고리즘

목록 보기
12/15
post-thumbnail

전력망을 둘로 나누기

프로그래머스 전력망을 둘로 나누기 풀이

문제 설명

n개의 송전탑이 전선을 통해 하나의 트리 형태로 연결되어 있습니다. 당신은 이 전선들 중 하나를 끊어서 현재의 전력망 네트워크를 2개로 분할하려고 합니다. 이때, 두 전력망이 갖게 되는 송전탑의 개수를 최대한 비슷하게 맞추고자 합니다.

송전탑의 개수 n, 그리고 전선 정보 wires가 매개변수로 주어집니다. 전선들 중 하나를 끊어서 송전탑 개수가 가능한 비슷하도록 두 전력망으로 나누었을 때, 두 전력망이 가지고 있는 송전탑 개수의 차이(절대값)를 return 하도록 solution 함수를 완성해주세요.

제한사항

  • n은 2 이상 100 이하인 자연수입니다.
  • wires는 길이가 n-1인 정수형 2차원 배열입니다.
    • wires의 각 원소는 [v1, v2] 2개의 자연수로 이루어져 있으며, 이는 전력망의 v1번 송전탑과 v2번 송전탑이 전선으로 연결되어 있다는 것을 의미합니다.
    • 1 ≤ v1 < v2 ≤ n 입니다.
    • 전력망 네트워크가 하나의 트리 형태가 아닌 경우는 입력으로 주어지지 않습니다.

풀이

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;
}
profile
두려움 없이

0개의 댓글