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;
}
}