알고리즘/그래프 탐색

[BOJ 9466] 텀 프로젝트 (Java, DFS)

leejinwoo1126 2023. 6. 14. 16:09
반응형

 


문제 링크

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

 

9466번: 텀 프로젝트

이번 가을학기에 '문제 해결' 강의를 신청한 학생들은 텀 프로젝트를 수행해야 한다. 프로젝트 팀원 수에는 제한이 없다. 심지어 모든 학생들이 동일한 팀의 팀원인 경우와 같이 한 팀만 있을

www.acmicpc.net


해당 문제에 대한 아이디어가 떠오르지 않아, 기술 블로그를 찾아보았고
visit 배열 말고, finish 배열을 활용하여 그래프 노드를 구하는 기법을 알 수 있었다.

 

풀이 

- 각 case 별 사이클 발생하는 인원 수를 구한 후 전체 학생 수와의 차이 구함 

- N이 최대 10^5 이기때문에 O(N^2)으로 풀 경우 10^10 이므로 '시간 초과' 발생 가능

- finish 배열 활용하여 이미 탐색이 끝난 경로의 경우 재탐색하지 않도록 하여 시간 복잡도 O(N) 만에 풀이 가능

1 -> 3 -> 3  // 자기 자신 가르키는 경우
2 -> 1 -> 3 -> 3

4 -> 7 -> 6 -> 4  // 사이클 발생 ( = 팀)

5 -> 3 -> 3

제출 코드

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

public class Main {
    
   static StringBuilder sb = new StringBuilder();

    static int T, N, TEAM_COUNT;

    static int[] student;

    static boolean[] visit, finish;

    static void input() throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        T = Integer.parseInt(st.nextToken());
        while(T > 0) {
            T -= 1;

            st = new StringTokenizer(br.readLine());
            N = Integer.parseInt(st.nextToken());

            st = new StringTokenizer(br.readLine());
            student = new int[N + 1];
            for(int i = 1; i <= N; i++) {
                student[i] = Integer.parseInt(st.nextToken());
            }

            visit = new boolean[N + 1];
            finish = new boolean[N + 1];
            TEAM_COUNT = 0;

            pro();
        }

        br.close();
    }

    static void dfs(int x) {
        visit[x] = true;

        int y = student[x];
        if(!visit[y]) {
            dfs(y);
        } else if(!finish[y]) {
            int cnt = 1;
            while(x != y) {
                y = student[y];
                cnt += 1;
            }

            TEAM_COUNT += cnt;
        }

        finish[x] = true;
    }

    static void pro() {
        for(int i = 1; i <= N; i++) {
            if(!visit[i]) dfs(i);
        }

        sb.append(N - TEAM_COUNT).append("\n");
    }

    public static void main(String[] args) throws Exception {
        input();
        System.out.println(sb);
    }
    
}
반응형