TIL

오랜만에 백준 코테

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

약간 그래프적인 느낌도 있고, 수학느낌도 있었음.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;

public class Main {
    static int[] arr;
    static int[] state; // 0: 방문 안 함, 1: 방문 중(현재 경로), 2: 방문 완료
    static Set<Integer> cycleLengths = new HashSet<>();

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
        
        arr = new int[N + 1];
        StringTokenizer st = new StringTokenizer(br.readLine());
        for (int i = 1; i <= N; i++) {
            arr[i] = Integer.parseInt(st.nextToken());
        }

        state = new int[N + 1];
        
        // 1. 모든 노드에 대해 사이클 탐색
        for (int i = 1; i <= N; i++) {
            if (state[i] == 0) {
                List<Integer> path = new ArrayList<>();
                int curr = i;
                
                // 경로 추적
                while (state[curr] == 0) {
                    state[curr] = 1; // 현재 경로 방문 표시
                    path.add(curr);
                    curr = arr[curr];
                }
                
                // 이미 방문 중인 노드를 만났다면 사이클 발견 (현재 경로 내에서의 재방문)
                if (state[curr] == 1) {
                    // curr 노드가 사이클의 시작점
                    // 사이클 길이 계산: curr에서 출발해 다시 curr로 돌아올 때까지의 거리
                    int len = 0;
                    int temp = curr;
                    do {
                        temp = arr[temp];
                        len++;
                    } while (temp != curr);
                    cycleLengths.add(len);
                }
                
                // 경로 상의 모든 노드를 방문 완료 처리
                for (int node : path) {
                    state[node] = 2;
                }
            }
        }

        // 2. 길이가 1인 사이클(자기 자신으로 돌아옴)이 있으면 무조건 불가능
        if (cycleLengths.contains(1)) {
            System.out.println(-1);
            return;
        }

        // 3. 모든 사이클 길이보다 큰 가장 작은 소수를 찾음
        // (어떤 사이클 길이의 배수도 되지 않게 하기 위함)
        int maxLen = 0;
        for (int len : cycleLengths) {
            maxLen = Math.max(maxLen, len);
        }
        
        // 문제 조건: 최소 2개 이상
        if (maxLen == 0) maxLen = 1; 

        int k = maxLen + 1;
        while (true) {
            if (isPrime(k)) {
                System.out.println(k);
                break;
            }
            k++;
        }
    }

    private static boolean isPrime(int n) {
        if (n < 2) return false;
        for (int i = 2; i * i <= n; i++) {
            if (n % i == 0) return false;
        }
        return true;
    }
}

results matching ""

    No results matching ""