10451번 순열 사이클
문제
1부터 N까지 정수 N개로 이루어진 순열을 나타내는 방법은 여러 가지가 있다. 예를 들어, 8개의 수로 이루어진 순열 (3, 2, 7, 8, 1, 4, 5, 6)을 배열을 이용해 표현하면 (1234567832781456)와 같다. 또는, Figure 1과 같이 방향 그래프로 나타낼 수도 있다.
순열을 배열을 이용해 (1…i…nπ1…πi…πn) 로 나타냈다면, i에서 πi로 간선을 이어 그래프로 만들 수 있다.
Figure 1에 나와있는 것 처럼, 순열 그래프 (3, 2, 7, 8, 1, 4, 5, 6) 에는 총 3개의 사이클이 있다. 이러한 사이클을 "순열 사이클" 이라고 한다.
N개의 정수로 이루어진 순열이 주어졌을 때, 순열 사이클의 개수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스의 첫째 줄에는 순열의 크기 N (2 ≤ N ≤ 1,000)이 주어진다. 둘째 줄에는 순열이 주어지며, 각 정수는 공백으로 구분되어 있다.
출력
각 테스트 케이스마다, 입력으로 주어진 순열에 존재하는 순열 사이클의 개수를 출력한다.
예제 입력
2
8
3 2 7 8 1 4 5 6
10
2 1 3 4 5 6 7 9 10 8
예제 출력
3
7
해결방법
사이클을 구하는 문제이다
이 문제에서는 사이클은 순열
이라는 조건을 줬다
다시 말해서 모든 노드는 사이클이 존재한다는 뜻이다 (노드의 간선 간에는 중복이 없다)
그렇다면 이와 같이 간단하게 코드를 작성할 수 있다
void dfs(int now){
visited[now] = true;
int nxt = arr[now];
if(!visited[nxt]){
dfs(nxt);
}
}
소스코드
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <bitset>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
#define MAX 1001
#define INF 987654321
using namespace std;
int testcase;
int n,ans;
int arr[MAX];
bool visited[MAX];
void dfs(int now){
visited[now] = true;
int nxt = arr[now];
if(!visited[nxt]){
dfs(nxt);
}
}
int main(int argc, const char * argv[]) {
// cin,cout 속도향상
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> testcase;
for(int t=0; t<testcase; t++){
cin >> n;
for(int i=1; i<=n; i++){
cin >> arr[i];
}
memset(visited, false, sizeof(visited));
ans = 0;
for(int i=1; i<=n; i++){
if(!visited[i]){
dfs(i);
ans++;
}
}
cout << ans << "\n";
}
}
'Algorithm > BOJ 문제풀이' 카테고리의 다른 글
[DFS] 2210번 숫자판 점프 (0) | 2018.12.16 |
---|---|
[DFS] 9466번 텀 프로젝트 (0) | 2018.12.16 |
[DFS] 1799번 비숍 (0) | 2018.12.16 |
[DFS] 2580번 스도쿠 (0) | 2018.12.16 |
[DFS] 1743번 음식물 피하기 (0) | 2018.12.16 |