Algorithm 2023. 6. 13.

[ν”„λ‘œκ·Έλž˜λ¨ΈμŠ€] μ „λ ₯망을 λ‘˜λ‘œ λ‚˜λˆ„κΈ°

Question

문제 μ„€λͺ…

n개의 솑전탑이 전선을 톡해 ν•˜λ‚˜μ˜ 트리 ν˜•νƒœλ‘œ μ—°κ²°λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. 당신은 이 μ „μ„ λ“€ 쀑 ν•˜λ‚˜λ₯Ό λŠμ–΄μ„œ ν˜„μž¬μ˜ μ „λ ₯망 λ„€νŠΈμ›Œν¬λ₯Ό 2개둜 λΆ„ν• ν•˜λ €κ³  ν•©λ‹ˆλ‹€. μ΄λ•Œ, 두 μ „λ ₯망이 κ°–κ²Œ λ˜λŠ” μ†‘μ „νƒ‘μ˜ 개수λ₯Ό μ΅œλŒ€ν•œ λΉ„μŠ·ν•˜κ²Œ λ§žμΆ”κ³ μž ν•©λ‹ˆλ‹€.

μ†‘μ „νƒ‘μ˜ 개수 n, 그리고 μ „μ„  정보 wiresκ°€ λ§€κ°œλ³€μˆ˜λ‘œ μ£Όμ–΄μ§‘λ‹ˆλ‹€. μ „μ„ λ“€ 쀑 ν•˜λ‚˜λ₯Ό λŠμ–΄μ„œ 솑전탑 κ°œμˆ˜κ°€ κ°€λŠ₯ν•œ λΉ„μŠ·ν•˜λ„λ‘ 두 μ „λ ₯망으둜 λ‚˜λˆ„μ—ˆμ„ λ•Œ, 두 μ „λ ₯망이 가지고 μžˆλŠ” 솑전탑 개수의 차이(μ ˆλŒ€κ°’)λ₯Ό return ν•˜λ„λ‘ solution ν•¨μˆ˜λ₯Ό μ™„μ„±ν•΄μ£Όμ„Έμš”.

μ œν•œμ‚¬ν•­

  • n은 2 이상 100 μ΄ν•˜μΈ μžμ—°μˆ˜μž…λ‹ˆλ‹€.
  • wiresλŠ” 길이가 n-1인 μ •μˆ˜ν˜• 2차원 λ°°μ—΄μž…λ‹ˆλ‹€.
    • wires의 각 μ›μ†ŒλŠ” [v1, v2] 2개의 μžμ—°μˆ˜λ‘œ 이루어져 있으며, μ΄λŠ” μ „λ ₯망의 v1번 솑전탑과 v2번 솑전탑이 μ „μ„ μœΌλ‘œ μ—°κ²°λ˜μ–΄ μžˆλ‹€λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€.
    • 1 ≤ v1 < v2 ≤ n μž…λ‹ˆλ‹€.
    • μ „λ ₯망 λ„€νŠΈμ›Œν¬κ°€ ν•˜λ‚˜μ˜ 트리 ν˜•νƒœκ°€ μ•„λ‹Œ κ²½μš°λŠ” μž…λ ₯으둜 주어지지 μ•ŠμŠ΅λ‹ˆλ‹€.

μž…μΆœλ ₯ 예

n wires result
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

Solve

풀이 κ³Όμ •

  1. wires의 λ…Έλ“œλ“€μ„ ν•˜λ‚˜μ”© μ œμ™Έν•œ λ…Έλ“œλ“€λ‘œ 트리λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.
  2. DFS ν˜Ήμ€ BFSλ₯Ό μ΄μš©ν•˜μ—¬ 트리λ₯Ό μˆœνšŒν•˜λ©° λŠμ–΄μ§„ 트리의 λ…Έλ“œ κ°œμˆ˜μ™€ λ°˜λŒ€ 트리의 λ…Έκ·Έ 개수λ₯Ό κ΅¬ν•΄μ€λ‹ˆλ‹€.
  3. 두 트리의 λ…Έλ“œ 개수의 차이가 κ°€μž₯ μž‘μ€ 값을 μ •λ‹΅μœΌλ‘œ λ¦¬ν„΄ν•©λ‹ˆλ‹€.

풀이 μ½”λ“œ

const solution = (n, wires) => {
  let answer = n;

  for (let i = 0; i < wires.length; i++) {
    const tree = makeTree(n, wires, i);
    const startNode = tree.findIndex((v) => !!v.length);
    const nodeCount = countNode(tree, startNode);
        // κ΅¬ν•œ 트리 λ…Έλ“œ κ°œμˆ˜μ™€ 총 λ…Έλ“œ 개수λ₯Ό μ΄μš©ν•˜μ—¬ λ°˜λŒ€ 트리 λ…Έλ“œ κ°œμˆ˜λ„ ꡬ해쀀닀.
    const abs = Math.abs(nodeCount * 2 - n);

    if (abs < answer) answer = abs;
  }

    return answer;
};

// 트리 생성 둜직
const makeTree = (n, wires, exceptIdx) => {
  const tree = Array.from({ length: n + 1 }, () => []);
  wires.forEach((wire, idx) => {
    if (idx === exceptIdx) return;
    const [a, b] = wire;
    tree[a].push(b);
    tree[b].push(a);
  });

  return tree;
};

// 트리의 λ…Έλ“œ 개수λ₯Ό κ΅¬ν•˜λŠ” 둜직
const countNode = (tree, startNode) => {
  const visited = [];
  let needVisit = [startNode];

  while (!!needVisit.length) {
    const node = needVisit.shift();

    if (!visited.includes(node)) {
      visited.push(node);
      needVisit = [...tree[node], ...needVisit];
    }
  }

    // λ°©λ¬Έν–ˆλ˜ λ…Έλ“œλ“€μ˜ 개수 = 트리의 λ…Έλ“œ 개수
  return visited.length;
};