보기보다 까다로운 문제다. (너무 지저분해서 내 코드를 완벽히 설명하기가 힘들 거 같다...)
처음에는 쌍을 찾기위해서 check 배열을 선언해서 각 testCase마다 초기화했었다.
하지만 시간이 한참 초과되는 걸 보고 check 배열을 초기화하는 대신 각 testCase마다 특정 수를 이용해서
하나의 check 배열을 재활용할 수 있도록 했다.
DFS 함수에서 정답을 찾으면 skip 배열에 해당 testCase에 해당하는 특정 수를 부여해주고
이후 탐색한 순서 역순으로 되돌아가면서
해당하는 수의 skip 배열에 testCase에 해당하는 특정 수를 부여하고 sum을 +1 한다.
DFS함수가 종료되면 쌍을 갖춘 학생들의 합인 sum과 총 학생 수인 len의 차이를 출력한다.
#include <iostream>
#include <cstring>
int check[100001] = { 0 };
int skip[100001] = { 0 };
int map[100001] = { 0 };
int sum = 0;
void DFS(int stu[], int start, int cur, int seq) {
check[cur] = seq;
if(start == cur && skip[cur] != seq) {
skip[cur] = seq;
sum++;
return;
}
if(stu[cur] == cur || check[stu[cur]] == seq || skip[stu[cur]] == seq) {
check[stu[cur]] = 0;
return;
}
DFS(stu, start, stu[cur], seq);
if(skip[stu[cur]] == seq && sum > 0) {
skip[cur] = seq;
sum++;
}
else {
check[stu[cur]] = 0;
}
}
int main(void) {
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
memset(check, 0, sizeof(check));
memset(skip, 0, sizeof(skip));
memset(map, 0, sizeof(map));
int testCase;
std::cin >> testCase;
int len, seq = 0;
for(int i = 0; i < testCase; i++) {
std::cin >> len;
sum = 0;
seq = testCase + 1;
for(int i = 1; i <= len; i++) {
std::cin >> map[i];
}
for(int idx = 1; idx <= len; idx++) {
if(skip[idx] == seq) continue;
DFS(map, idx, map[idx], seq);
}
std::cout << len - sum << "\n";
}
return 0;
}
|
cs |
'problem solving' 카테고리의 다른 글
10610번: 30 (0) | 2020.03.04 |
---|---|
9613번: GCD 합 (0) | 2020.03.04 |
9019번: DSLR (0) | 2020.03.03 |
7576번: 토마토 (0) | 2020.03.03 |
6588번: 골드바흐의 추측 (0) | 2020.03.03 |