[프로그래머스] 전력망을 둘로 나누기 - Java

JeongYong·2023년 6월 30일
0

Algorithm

목록 보기
179/275

문제 링크

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

문제

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

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

제한사항

알고리즘: DFS, 트리, 그래프

풀이

이 문제는 주어진 전선 중 하나를 끊었을 때 두 전력망이 가지고 있는 송전탑 개수의 차이(절대값)가 가장 작은 값을 출력하는 문제다.

제한사항을 보면 전력망 네트워크가 하나의 트리 형태가 아닌 경우는 입력으로 주어지지 않는다는 의미는 주어진 tree는 어떤 정점에서 시작해도 모든 정점을 방문할 수 있다는 의미이다.

임의의 정점에서 깊이 우선 탐색을 시작했을 때 모든 정점에서 자식 노드의 개수(송전탑의 개수)를 구할 수 있다. 그러면 그 정점에서 부모로 가는 선을 끊었다고 가정해 보자, 하나의 전력망이 두 전력망으로 나눠지고 우리는 두 전력망이 가지고 있는 송전탑 개수를 구할 수 있다. -> (자식 노드의 개수, (전체 노드의 개수 - 자식 노드의 개수))

마지막으로 두 전력망이 가지고 있는 송전탑 개수의 차이 중 가장 작은 값을 출력하면 된다.

위 풀이는 O(n) 풀이이고, n의 범위는 2 이상 100 이하이기 때문에 O(n^2) 풀이도 가능하다. - > (그냥 모든 전선을 하나씩 끊고 깊이 우선 탐색하는 방식)

소스 코드

import java.util.*;
class Solution {
    static ArrayList<ArrayList<Integer>> graph = new ArrayList<>();
    static boolean[] visited;
    static int answer = Integer.MAX_VALUE;
    static int N;
    public int solution(int n, int[][] wires) {
        N = n;
        visited = new boolean[n + 1];
        for(int i=0; i<=n; i++) graph.add(new ArrayList<>());
        for(int i=0; i<wires.length; i++) {
            graph.get(wires[i][0]).add(wires[i][1]);
            graph.get(wires[i][1]).add(wires[i][0]);
        }
        DFS(1);
        return answer;
    }
    
    static int DFS(int a) {
        int cnt = 1;
        visited[a] = true;
        for(int i=0; i<graph.get(a).size(); i++) {
            int b = graph.get(a).get(i);
            if(!visited[b]) cnt += DFS(b);
        }
        answer = Math.min(answer, Math.abs((N - cnt) - cnt));
        return cnt;
    }
}

0개의 댓글