반응형
문제 출처 :
https://www.acmicpc.net/problem/9466
알고리즘 분석 :
문제 해결에 필요한 사항
1. Union Find의 Find 방식
2. 집합
유니온 파인드의 파인드 방식을 생각하면서 풀면 이해하기가 좀 더 쉽다.(사이클에 대한 개념을)
이 문제는 3가지 경우로 나눌 수 있다.
이 세가지 방식에 대해 처리를 해주면 쉽게 해결 할 수 있다.
단, 노드를 하나씩 방문하는 것이 아닌, 이미 사이클 탐색을 시작하는 순간 그 노드들은 방문했는 것으로 처리해도 된다는 것이다.
예를들어 3번째그림의 모습을 보면 1->2->3->4->2로 반복되는데 2,3,4는 사이클이지만 1은 사이클이 아니다.
따라서 1을 탐색한 순간 2,3,4도 모두 탐색이 완료된 상태로 생각 할 수 있다.
소스 코드를 통해 어떻게 탐색을하고 탐색한 노드를 어떻게 처리하는지 알아보자.
소스 코드 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | #include <iostream> #include <cstdio> #include <memory.h> #include <vector> using namespace std; int parent[100002]; int visit[100002]; int prevNum[100002]; int cycleTest; vector<int> cycle; int isCycle(int root, int prev, int here, int cnt) { // 이미 체크된 노드에 대해서는 return -1 if (parent[here] == -1) return -1; // 현재 cycleTest번째에 이미 방문한 적이 있는가? if (visit[here] == cycleTest) { // 시작->끝이 사이클인가? if (here == root) return cnt - 1; // 시작->끝이 사이클이 아니라면 사이클이 그사이 존재했는것 // 따라서 꼬리부분을 제외한 사이클 부분을 return return cnt - prevNum[here]; } // 자신의 뒷부분에 따라오는 노드를 추가 prevNum[here] = prevNum[prev] + 1; // here은 cycleTest번째에 방문을 하고있다 visit[here] = cycleTest; // 그에 해당하는 here을 벡터에 담아둔다.(사이클이든 아니든) cycle.push_back(here); return isCycle(root, here, parent[here], cnt + 1); } int main() { int tCase; scanf("%d", &tCase); while (tCase--) { int n; int ans = 0; scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &parent[i]); for (int i = 1; i <= n; i++) { // 이미 체크된 노드라면 continue; if (parent[i] == -1) continue; // cycleTest번째를 늘려준다.(visit를 memset하는것 대신 이용) cycleTest++; cycle.clear(); // get에는 사이클의 크기가 담겨온다. int get = isCycle(i, 0, i, 1); // 사이클이 존재한다면 if (get != -1) { ans += get; cycleTest++; } // 사이클이었든 아니었든 벡터에 담긴 값들은 모두 -1로 없앤다. int len = cycle.size(); for (int i = 0; i < len; i++) parent[cycle[i]] = -1; } // 전체 노드 - 사이클을 이룬 수 printf("%d\n", n - ans); } return 0; } // This source code Copyright belongs to Crocus // If you want to see more? click here >> | Crocus |
반응형
'Applied > 알고리즘 문제풀이' 카테고리의 다른 글
[1168번] 조세퍼스 문제 2 (0) | 2017.03.29 |
---|---|
[1017번] 소수 쌍 (0) | 2017.03.29 |
[6603번] 로또 (7) | 2017.03.29 |
[6549번] 히스토그램에서 가장 큰 직사각형 (7) | 2017.03.28 |
[1759번] 암호 만들기 (2) | 2017.03.28 |