[BOJ] 9466: 텀 프로젝트 (JAVA)

2024. 6. 22. 19:26·Algorithm/BFS & DFS

문제

https://www.acmicpc.net/problem/9466

 

여담

처음에 BFS 방식으로 사이클을 찾으려고 했다가 계속 시간초과가 발생했다. 찾아보니 사이클을 판별할 때는 DFS 탐색을 사용해야 한다고 한다.. 그래프 탐색으로 사이클을 찾을 때는 DFS 탐색 & 배열 2개를 기억하자!

 

풀이

프로젝트를 함께 하고 싶은 학생을 선택한 것을 연결했을 때, 사이클이 발생하면 하나의 팀을 구성할 수 있다.

  • 1번 학생이 2번 선택, 2번 학생이 3번 선택
    • 1 → 2 → 3 ... (단방향)

 

사이클을 탐지하기 위해 DFS 탐색 시 방문 여부를 기록하는 visited 배열과 팀 구성 여부를 기록하는 check 배열, 즉 총 2개의 배열을 생성해야 한다.

 

우선 선택의 결과를 입력받고 팀 구성이 완료되지 않은 학생만 DFS 탐색을 수행하면 된다. 이때, 자신이 자신의 선택한 경우도 팀이 구성된 것이므로, 팀 구성 완료 처리를 해주면 된다. 

 

DFS 탐색 과정은 다음과 같다.

  1. 확인하는 학생의 팀 구성이 완료된 경우라면 탐색을 종료하기
  2. 팀 구성이 완료되지 않았고, 이미 방문한 경우라면 사이클이 생성된 것
    • 팀 구성 완료 처리하기: check[x] = true
  3. 처음 방문한 경우라면, 방문 처리를 한 뒤 DFS 탐색하기 (재귀호출)
  4. DFS 탐색이 끝나기 전, 사이클에 포함되지 않더라도 팀 구성 여부를 확인했으므로 상태 변경하기

 

자세한 내용은 아래의 코드를 참고하면 된다.

 

코드

import java.io.*;
import java.util.*;

public class Main {
    static int N, answer;
    static int[] students;
    static boolean[] check, visited;
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int T = Integer.parseInt(br.readLine());

        StringBuilder sb = new StringBuilder();
        for (int t = 0; t < T; t++) {
            N = Integer.parseInt(br.readLine());
            students = new int[N + 1];
            check = new boolean[N + 1];
            visited = new boolean[N + 1];
            answer = N;

            StringTokenizer st = new StringTokenizer(br.readLine(), " ");
            for (int i = 1; i <= N; i++) {
                students[i] = Integer.parseInt(st.nextToken());
                if (students[i] == i) { // 자기 자신과 팀을 이루는 경우
                    check[i] = true;
                    answer--;
                }
            }

            for (int i = 1; i <= N; i++) {
                if (!check[i]) {
                    dfs(i);
                }
            }
            sb.append(answer).append("\n");
        }
        System.out.println(sb.toString());
    }

    static void dfs(int x) {
        if (check[x]) return; // 이미 사이클 여부를 확인한 곳은 탐색할 필요 X
        if (visited[x]) { // 이미 방문한 지점을 방문한 경우
            answer--;
            check[x] = true;
        }

        visited[x] = true;
        dfs(students[x]);
        visited[x] = false;

        check[x] = true; // 팀을 구성하지 않았어도, 사이클 여부를 확인했으므로 true로 변경
    }
}

참고

https://iseunghan.tistory.com/317

https://yeeybook.tistory.com/147

 

'Algorithm > BFS & DFS' 카테고리의 다른 글

[BOJ] 문제 풀이 모음집 - BFS/DFS 2 (JAVA)  (0) 2024.07.01
[BOJ] 2146: 다리 만들기 (JAVA)  (0) 2024.06.24
[BOJ] 문제 풀이 모음집 - BFS/DFS (JAVA)  (0) 2024.06.17
[BOJ] 2638: 치즈 (JAVA)  (0) 2024.05.01
[BOJ] 16932: 모양 만들기 (JAVA)  (1) 2024.04.26
'Algorithm/BFS & DFS' 카테고리의 다른 글
  • [BOJ] 문제 풀이 모음집 - BFS/DFS 2 (JAVA)
  • [BOJ] 2146: 다리 만들기 (JAVA)
  • [BOJ] 문제 풀이 모음집 - BFS/DFS (JAVA)
  • [BOJ] 2638: 치즈 (JAVA)
hjin28
hjin28
  • hjin28
    끄적이는 기록장
    hjin28
  • 전체
    오늘
    어제
  • 블로그 메뉴

    • 홈
    • 태그
    • GitHub
    • 이전 블로그
    • 분류 전체보기
      • TIL
      • Frontend
      • Backend
      • Infra
      • Java
        • 이것이 자바다
      • CS
        • 컴퓨터구조
        • 운영체제
        • 네트워크
        • 데이터베이스
      • Algorithm
        • 자료구조
        • 시뮬레이션
        • 완전탐색
        • BFS & DFS
        • DP
        • 그리디
        • 최단경로
        • 유니온파인드
        • 위상정렬
        • 정렬
        • SQL
      • ETC
  • 최근 글

  • 태그

    백준
    DFS
    그리디
    SWEA
    덱
    다익스트라
    구현
    vue
    til
    SQL
    자바
    자료구조
    springsecurity
    ec2
    BFS
    투포인터
    다이나믹프로그래밍
    컴퓨터구조
    Programmers
    비트마스킹
    DP
    완전탐색
    백트래킹
    Spring
    위상정렬
    JWT
    java
    최단경로
    websocket
    유니온파인드
  • hELLO· Designed By정상우.v4.10.1
hjin28
[BOJ] 9466: 텀 프로젝트 (JAVA)
상단으로

티스토리툴바