[백준] 1325 효율적인 해킹 (JAVA)

2025. 9. 3. 15:34·코딩 테스트

문제링크:

1325번: 효율적인 해킹

 

 

문제:

해커 김지민은 잘 알려진 어느 회사를 해킹하려고 한다. 이 회사는 N개의 컴퓨터로 이루어져 있다. 김지민은 귀찮기 때문에, 한 번의 해킹으로 여러 개의 컴퓨터를 해킹 할 수 있는 컴퓨터를 해킹하려고 한다.

 

이 회사의 컴퓨터는 신뢰하는 관계와, 신뢰하지 않는 관계로 이루어져 있는데, A가 B를 신뢰하는 경우에는 B를 해킹하면, A도 해킹할 수 있다는 소리다.

 

이 회사의 컴퓨터의 신뢰하는 관계가 주어졌을 때, 한 번에 가장 많은 컴퓨터를 해킹할 수 있는 컴퓨터의 번호를 출력하는 프로그램을 작성하시오.

 

 

입력:

첫째 줄에, N과 M이 들어온다. N은 10,000보다 작거나 같은 자연수, M은 100,000보다 작거나 같은 자연수이다. 둘째 줄부터 M개의 줄에 신뢰하는 관계가 A B와 같은 형식으로 들어오며, "A가 B를 신뢰한다"를 의미한다. 컴퓨터는 1번부터 N번까지 번호가 하나씩 매겨져 있다.

 

 

출력:

첫째 줄에, 김지민이 한 번에 가장 많은 컴퓨터를 해킹할 수 있는 컴퓨터의 번호를 오름차순으로 출력한다.

 

 

문제이해:

이 문제를 이해하기 위해서 예제 입력 1을 예를들어 설명한다.

대표적으로 1을 예를 들어보면 3->1을신뢰하므로 1을 해킹하면 3을 해킹할 수 있고,

 

4번 5번이 3을 신뢰하므로 4번 5번도 해킹할 수 있어 자신을 제외한 3,4,5 3개를 해킹 할 수 있는 것이다.

 

 

구현방향:

이 문제는 주어진 컴퓨터들 사이의 신뢰 관계를 그래프로 표현하고, 각 컴퓨터를 시작점으로 잡아 얼마나 많은 다른 컴퓨터까지 해킹이 퍼질 수 있는지를 세는 방식으로 해결할 수 있는 문제이다.

 

입력으로 주어지는 a b라는 관계는 “b를 해킹하면 a도 해킹된다”는 의미이다. 따라서 간선은 단순히 a → b 방향이 아니라 b에서 a로 향하는 방향으로 저장해야 한다. 이렇게 해야 특정 노드 b를 시작점으로 탐색을 진행할 때, 실제 해킹 전파가 일어나는 흐름과 일치하게 된다.

 

그래프를 표현할 때는 인접 행렬을 사용하면 메모리 사용량이 O(N^2)으로 매우 커져 제한에 걸리기 쉽다. 따라서 실제로 존재하는 간선만 저장하는 인접 리스트를 사용하는 것이 적절하다. 코드에서는 List<Integer>[] arr 배열을 선언하고 각 칸을 new ArrayList<>()로 초기화한 후, 입력을 받을 때마다 arr[b].add(a)로 관계를 추가한다.

 

탐색은 깊이 우선 탐색(DFS)으로 구현한다. 각 노드를 하나의 시작점으로 두고 DFS를 수행하며, 매번 탐색을 시작하기 전에 visited 배열을 false로 초기화하여 이전 탐색의 흔적이 남지 않도록 한다. 탐색 도중 새롭게 방문한 노드를 발견할 때마다 해당 시작점의 해킹 가능 개수를 하나씩 증가시켜 기록한다.

 

모든 노드를 시작점으로 탐색한 이후에는, result 배열에 기록된 값들 중 가장 큰 값을 찾는다. 이 값이 곧 가장 많은 컴퓨터를 해킹할 수 있는 경우의 수이다. 마지막으로, 최대값과 같은 결과를 가진 노드 번호들을 출력하면 정답이 된다.

 

정답코드:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;

public class Main {
    static int N, M;
    static List<Integer>[]arr;
    static boolean[] visited;
    static int[] result;
    static int max = 0;


    //dfs탐색
    public static void dfs(int start, int cur) {
        visited[cur] = true;
        for (int next : arr[cur]) {
            if (!visited[next]) {
                result[start]++;
                dfs(start, next);
            }
        }
    }


    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        // 초기 세팅
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());

        // 인접 리스트 초기화
        arr = new ArrayList[N + 1];
        for (int i = 1; i <= N; i++) {
            arr[i] = new ArrayList<>();
        }
        visited = new boolean[N + 1];
        result = new int[N + 1];

        for (int i = 0; i < M; i++) {
            String str = br.readLine();
            String[] split = str.split(" ");
            int a = Integer.parseInt(split[0]);
            int b = Integer.parseInt(split[1]);
            arr[b].add(a); // b -> a 간선
        }
        // 세팅 끝

        // dfs 탐색
        for (int i = 1; i <= N; i++) {
            Arrays.fill(visited, false);
            dfs(i, i);
        }

        // 최대값 찾기
        for (int i = 1; i <= N; i++) {
            if (result[i] > max) max = result[i];
        }

        // 최대값 가진 노드 번호 출력
        for (int i = 1; i <= N; i++) {
            if (max == result[i]) System.out.print(i + " ");
        }
    }
}

 

마무리하며:

이번 문제를 풀면서 처음에는 인접 행렬로 구현하였다가 메모리 초과를 경험하였다. 노드 수가 많을 때 인접 행렬은 모든 가능한 간선을 저장하기 때문에 불필요하게 큰 공간을 차지하게 된다. 반면 인접 리스트는 실제 존재하는 간선만을 저장하므로 메모리 사용을 크게 줄일 수 있었다. 이 과정을 통해 단순히 정답을 맞히는 것에 그치지 않고, 입력 크기와 메모리 제약을 고려하여 적절한 자료구조를 선택하는 자세가 필요하다는 점을 배울 수 있었다.

 

감사합니다.

'코딩 테스트' 카테고리의 다른 글

[백준] 2589 보물섬 (JAVA)  (0) 2025.09.11
[백준] 15686 치킨 배달 (JAVA)  (0) 2025.09.04
[백준] 1068 트리 (JAVA)  (0) 2025.09.02
[백준] 2636 치즈 (JAVA)  (6) 2025.07.26
[백준] 4949 균형잡힌 세상 (JAVA)  (1) 2025.07.11
'코딩 테스트' 카테고리의 다른 글
  • [백준] 2589 보물섬 (JAVA)
  • [백준] 15686 치킨 배달 (JAVA)
  • [백준] 1068 트리 (JAVA)
  • [백준] 2636 치즈 (JAVA)
0kingki_
0kingki_
자바 + 스프링 웹 개발
  • 0kingki_
    0kingki_
    0kingki_
  • 전체
    오늘
    어제
    • 분류 전체보기 (134)
      • 코딩 테스트 (54)
      • 자바 (21)
      • 스프링 (27)
      • 타임리프 (16)
      • 스프링 데이터 JPA (8)
      • 최적화 (2)
      • QueryDSL (4)
      • AWS (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    백준
    SpringDataJpa
    dfs
    JPA
    BFS
    스프링 컨테이너
    thymeleaf
    스프링 데이터 JPA
    fetch join
    스프링
    mvc
    쿼리
    불변객체
    Java
    예외 처리
    QueryDSL
    자바
    spring
    예외처리
    컬렉션
    타임리프
    LocalDateTime
    코딩테스트
    최적화
    다형성
    SOLID
    코딩 테스트
    쿼리dsl
    객체지향
    재귀
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
0kingki_
[백준] 1325 효율적인 해킹 (JAVA)
상단으로

티스토리툴바