https://www.acmicpc.net/problem/9466
학생이 한 명만 선택하므로 인접리스트 만들 필요없이 그냥 배열에 저장하면 됨
🌟done 배열 : 더 이상 방문하지 않을 것을 확신하는 경우에 true => 팀 매칭이 완료된 경우
방문은 했지만, 팀 매칭이 완료되지 않은 경우에 사이클에 포함된 노드 수 셈
🥝처음 보는 조건을 가진 for문!
for (int i = next; i != node; i = arr[i]) { //사이클에 속한 인원 확인
cnt++;
}
1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|
3 | 1 | 3 | 7 | 3 | 4 | 6 |
dfs(4)->dfs(7)->dfs(6)
node=6, next=4
i = next = 4
i = arr[4] = 7
i = arr[7] = 6 //반복문 탈출
#include <iostream>
#include <vector>
#include <string.h>
#include <algorithm>
using namespace std;
int arr[100001];
bool check[100001];
bool done[100001];
int cnt;
void dfs(int node) {
check[node] = true;
int next = arr[node];
if (!check[next]) {
dfs(next);
}
else if (!done[next]) { //방문은 했지만, 팀 매칭이 완료되지 않은 경우
for (int i = next; i != node; i = arr[i]) { //사이클에 속한 인원 확인
cnt++;
}
cnt++; //사이클 시작 학생 추가
}
done[node] = true; //팀 매칭 완료
}
int main() {
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> arr[i];
}
for (int i = 1; i <= n; i++) {
if (!check[i]) {
dfs(i);
}
}
cout << n - cnt << '\n';
//초기화
cnt = 0;
memset(arr, 0, sizeof(arr));
memset(check, false, sizeof(check));
memset(done, false, sizeof(done));
}
return 0;
}