전력망을 둘로 나누기

나주엽·2023년 12월 4일
0

프로그래머스

목록 보기
21/33
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 입니다.
  • 전력망 네트워크가 하나의 트리 형태가 아닌 경우는 입력으로 주어지지 않습니다.

입출력 예

nwiresresult
9[[1,3],[2,3],[3,4],[4,5],[4,6],[4,7],[7,8],[7,9]]3
4[[1,2],[2,3],[3,4]]0
7[[1,2],[2,7],[3,7],[3,4],[4,5],[6,7]]1

입출력 예 설명

입출력 예 #1

다음 그림은 주어진 입력을 해결하는 방법 중 하나를 나타낸 것입니다.

  • 4번과 7번을 연결하는 전선을 끊으면 두 전력망은 각 6개와 3개의 송전탑을 가지며, 이보다 더 비슷한 개수로 전력망을 나눌 수 없습니다.
  • 또 다른 방법으로는 3번과 4번을 연결하는 전선을 끊어도 최선의 정답을 도출할 수 있습니다.

입출력 예 #2

다음 그림은 주어진 입력을 해결하는 방법을 나타낸 것입니다.

  • 2번과 3번을 연결하는 전선을 끊으면 두 전력망이 모두 2개의 송전탑을 가지게 되며, 이 방법이 최선입니다.

입출력 예 #3

다음 그림은 주어진 입력을 해결하는 방법을 나타낸 것입니다.

  • 3번과 7번을 연결하는 전선을 끊으면 두 전력망이 각각 4개와 3개의 송전탑을 가지게 되며, 이 방법이 최선입니다.

풀이

1차 (92.3점)

트리를 만들고, 간선을 하나씩 끊어가면서 두 개의 송전탑 아래로 총 몇개가 있는지 확인해 보았다.

function solution(n, wires) {
    var answer = 100; // 최대값은 100을 넘을 수 없다.
    
    // 간단한 트리 
    const tree = new Array(n+1).fill(0).map(_ => []);
    wires.forEach(elem => {
        const [a,b] = elem;
        tree[a].push(b);
        tree[b].push(a);
    })
    
    // 특정 송전탑에서 연결된 모든 송전탑 개수를 세는 BFS (단, 특정 노드가 끊어졌을 경우를 고려)
    function BFS(start, disconnect) {
        let count = 0;
        const visited = [];
        const queue = [start];
        
        while (queue.length) {
            let node = queue.shift();
            
            tree[node].forEach((elem) => {
                if (elem !== disconnect && !visited.includes(elem)) {
                    visited.push(elem)
                    queue.push(elem);
                }
            })
            count++;
        }
        return count;
    }
    
    wires.forEach(elem => {
        const [a,b] = elem;
        const diff = Math.abs(BFS(a,b)-BFS(b,a));
        if (diff < answer) answer = diff;
    })
    
    return answer;
}
  • 테스트 1번 만 실패하고 모두 통과했다.

나와 같이 1번만 통과하지 못하는 사람들이 많은 듯 보였다.
반례를 구했다.

  • 반례 : n=4, [[1, 2], [1, 3], [1, 4]], return = 2
    나의 경우에는 리턴으로 3이 나왔다. 하나의 송전탑으로만 구성된 망의 경우 그 크기를 0으로 리턴하는 경우가 생겼기 때문이다.

따라서 이점을 개선했다.

2차 (성공)

우선 기본적으로 BFS의 카운트를 1로 수정하고, visited에 시작지점을 넣어서 수정했다.

function solution(n, wires) {
    var answer = 100;
    
    // 간단한 트리 
    const tree = new Array(n+1).fill(0).map(_ => []);
    wires.forEach(elem => {
        const [a,b] = elem;
        tree[a].push(b);
        tree[b].push(a);
    })
    
    // 특정 송전탑에서 연결된 모든 송전탑 개수를 세는 BFS (단, 특정 노드가 끊어졌을 경우를 고려)
    function BFS(start, disconnect) {
        let count = 1;
        const visited = [start];
        const queue = [start];
        
        while (queue.length) {
            let node = queue.shift();
            
            tree[node].forEach((elem) => {
                if (elem !== disconnect && !visited.includes(elem)) {
                    visited.push(elem)
                    queue.push(elem);
                }
            })
            count++;
        }
        return count;
    }
    
    wires.forEach(elem => {
        const [a,b] = elem;
        const diff = Math.abs(BFS(a,b)-BFS(b,a));
        if (diff < answer) answer = diff;
    })
    return answer;
}

0개의 댓글