KimMinJun
Coding Note
KimMinJun
전체 방문자
오늘
어제
  • 분류 전체보기 (517) N
    • Project (1)
      • blog (1)
    • CS (1)
    • Web (29)
      • Vanilla JS (13)
      • TS (2)
      • React (7)
      • Next.js (5)
      • ETC (1)
    • Docker (14)
    • Git (5)
    • ALGORITHM (11)
      • 정렬 (6)
      • 최단경로 (1)
      • 자료구조 (1)
      • 슬라이딩 윈도우 (1)
      • etc (2)
    • PS (441) N
      • 백준 (187)
      • Programmers (114) N
      • CodeUp (21)
      • STL (3)
      • 제코베 JS 100제 (50)
      • SWEA (0)
      • LeetCode (65)
    • IT (1)
    • React 공식문서 (번역, 공부) (11)
      • Quick Start (2)
      • Installation (0)
      • Describing the UI (9)
      • Adding Interactivity (0)
      • Managing State (0)
      • Escape Hatches (0)
    • Next.js 공식문서 (번역, 공부) (3)
      • Getting Started (2)
      • Building Your Application (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 관리

공지사항

인기 글

태그

  • tree
  • 다이나믹 프로그래밍
  • programmers
  • recursion
  • Level 2
  • 정렬
  • codeup
  • js
  • Level 1
  • C++
  • 백준
  • C
  • Level1
  • 문자열
  • Level 0
  • 수학
  • 그래프
  • 제코베 JS 100제
  • LeetCode
  • string

최근 댓글

최근 글

hELLO · Designed By 정상우.
KimMinJun

Coding Note

Programmers / Level 2 / 전력망을 둘로 나누기 / JS
PS/Programmers

Programmers / Level 2 / 전력망을 둘로 나누기 / JS

2025. 9. 5. 11:49

https://school.programmers.co.kr/learn/courses/30/lessons/86971

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

풀이

/**
 * 인접리스트를 초기화하는 함수이다.
 *
 * @param {number[][]} wires 전선 정보
 * @returns {Map<number, Set<number>>} 인접리스트
 */
function initAdjList(wires) {
  const adjList = new Map();

  wires.forEach(([tower1, tower2]) => {
    if (adjList.has(tower1)) {
      adjList.get(tower1).add(tower2);
    } else {
      adjList.set(tower1, new Set([tower2]));
    }

    if (adjList.has(tower2)) {
      adjList.get(tower2).add(tower1);
    } else {
      adjList.set(tower2, new Set([tower1]));
    }
  });

  return adjList;
}

/**
 * bfs를 이용해 한 쪽 송전탑의 개수를 구하는 함수이다.
 *
 * @param {number} n 송전탑의 개수
 * @param {Map<number, Set<number>>} adjList 인접리스트
 * @returns 두 전력망으로 나누었을 때, 한 쪽의 송전탑의 개수
 */
function bfs(n, adjList) {
  // 임의로 1번 송전탑에서 시작한다.
  const queue = [1];
  const visited = Array.from({ length: n + 1 }, () => false);
  let count = 1;

  visited[1] = true;

  while (queue.length > 0) {
    const curTower = queue.shift();

    for (const nextTower of adjList.get(curTower)) {
      if (visited[nextTower]) {
        continue;
      }

      visited[nextTower] = true;
      queue.push(nextTower);
      count++;
    }
  }

  return count;
}

function solution(n, wires) {
  const adjList = initAdjList(wires);
  let result = Infinity;

  for (const [tower1, tower2] of wires) {
    // tower1과 tower2에 연결된 전선을 끊어준다.
    adjList.get(tower1).delete(tower2);
    adjList.get(tower2).delete(tower1);
    const count1 = bfs(n, adjList);
    const count2 = n - count1;
    // 위에서 끊어준 전선을 다시 이어준다.
    adjList.get(tower1).add(tower2);
    adjList.get(tower2).add(tower1);

    const diff = Math.abs(count1 - count2);
    result = Math.min(result, diff);
  }

  return result;
}

핵심 로직은 모든 전선을 하나씩 끊어보면서 나뉘어진 송전탑의 개수를 세주었다.

그래프는 인접리스트로 구현해주었는데,

수정, 삭제가 용이하도록 Map과 Set 자료구조를 이용해주었다.

 

`initAdjList(wires)`

/**
 * 인접리스트를 초기화하는 함수이다.
 *
 * @param {number[][]} wires 전선 정보
 * @returns {Map<number, Set<number>>} 인접리스트
 */
function initAdjList(wires) {
  const adjList = new Map();

  wires.forEach(([tower1, tower2]) => {
    if (adjList.has(tower1)) {
      adjList.get(tower1).add(tower2);
    } else {
      adjList.set(tower1, new Set([tower2]));
    }

    if (adjList.has(tower2)) {
      adjList.get(tower2).add(tower1);
    } else {
      adjList.set(tower2, new Set([tower1]));
    }
  });

  return adjList;
}

인접리스트를 초기화하는 함수이다.

Map 자료구조를 이용해주었다.

key는 송전탑, value는 key와 이어진 송전탑들을 Set 자료구조로 저장해주었다.

 

Set을 사용한 이유는,

delete()로 전선을 끊고, add()로 다시 전선을 붙이기 용이하기 때문이다.

 

`bfs(n, adjList)`

/**
 * bfs를 이용해 한 쪽 송전탑의 개수를 구하는 함수이다.
 *
 * @param {number} n 송전탑의 개수
 * @param {Map<number, Set<number>>} adjList 인접리스트
 * @returns 두 전력망으로 나누었을 때, 한 쪽의 송전탑의 개수
 */
function bfs(n, adjList) {
  // 임의로 1번 송전탑에서 시작한다.
  const queue = [1];
  const visited = Array.from({ length: n + 1 }, () => false);
  let count = 1;

  visited[1] = true;

  while (queue.length > 0) {
    const curTower = queue.shift();

    for (const nextTower of adjList.get(curTower)) {
      if (visited[nextTower]) {
        continue;
      }

      visited[nextTower] = true;
      queue.push(nextTower);
      count++;
    }
  }

  return count;
}

나뉘어진 전력망에서 연결된 송전탑의 개수는 bfs로 구해주었다.

첫 시작은 임의로 1번 송전탑에서 시작했는데,

어차피 이어진 송전탑은 다 탐색하기 때문에 아무 송전탑에서 시작해도 상관은 없다.

 

`solution(n, wires)`

function solution(n, wires) {
  const adjList = initAdjList(wires);
  let result = Infinity;

  for (const [tower1, tower2] of wires) {
    // tower1과 tower2에 연결된 전선을 끊어준다.
    adjList.get(tower1).delete(tower2);
    adjList.get(tower2).delete(tower1);
    const count1 = bfs(n, adjList);
    const count2 = n - count1;
    // 위에서 끊어준 전선을 다시 이어준다.
    adjList.get(tower1).add(tower2);
    adjList.get(tower2).add(tower1);

    const diff = Math.abs(count1 - count2);
    result = Math.min(result, diff);
  }

  return result;
}

 

모든 전선을 순회하면서, 하나씩 끊어보면서 개수를 세준다.

주의할 것은 다음 전선을 끊을 때는 이전에 끊었던 전선을 다시 붙여주어야 한다.

bfs로 한 쪽 전력망의 송전탑 개수를 구해줬다면,

총 송전탑의 개수에서 빼면 다른 쪽 전력망의 송전탑 개수를 구할 수 있다.

저작자표시 (새창열림)

'PS > Programmers' 카테고리의 다른 글

Programmers / Level 2 / 가장 큰 수 / JS  (0) 2025.09.09
Programmers / Level 2 / 양궁대회 / JS  (0) 2025.09.08
Programmers / Level 3 / 경주로 건설 / JS  (0) 2025.09.04
Programmers / Level 3 / 네트워크 / JS  (0) 2025.09.02
    'PS/Programmers' 카테고리의 다른 글
    • Programmers / Level 2 / 가장 큰 수 / JS
    • Programmers / Level 2 / 양궁대회 / JS
    • Programmers / Level 3 / 경주로 건설 / JS
    • Programmers / Level 3 / 네트워크 / JS
    KimMinJun
    KimMinJun

    티스토리툴바