문제 : https://www.acmicpc.net/problem/9466
문제
문제는 프로젝트 팀을 구성하기 위해, 모든 학생들은 프로젝트를 함께 하고 싶은 학생들을 선택하는데
어느 프로젝트 팀에도 속하지 않는 학생들의 수를 계산하는 문제이다.
풀이
이 문제는 DFS를 활용하여 Cycle을 이루는지 확인하는 방법으로 문제를 풀 수 있다.
DFS를 하다가, 싸이클이 발생하는 조건을 찾을 수 있다.
정점 방문을 시작했는지 체크하는 visited 배열,
그 정점의 방문함수가 완전히 끝났는지를 체크하는 finished 배열이 필요햐다.
다음에 방문할 정점을 k라고 했을때, visited[k] = true, finished[k] = false인 경우이다.
예를들어 1->2->3->1 이 싸이클을 이룬다고 가정해보자.
1번 정점에서 DFS를 시작했을 때, 1번 정점이 2번 정점을 부르고 2번 정점이 3번 정점을 부른다.
3번 정점이 다시 1번정점을 부를려고 했을 때 visited[1] = true, finished[1] = false이다.
따라서 1->2->3->1 이 싸이클임을 알 수 있다.
또한, 1->2->3->4 의 그래프가 있다고 가정해보자.
2번 3번 정점의 방문이 끝났고, 1번 정점 DFS를 시작했을때,
1번정점이 다음에 부르려는 2번 정점의 경우 visited[2] = true, finished[2] = true 이므로
1번정점은 싸이클 안에 없음을 알 수 있다.
| visited[next] = false | visited[next] = true |
finished[next] = false | 아직 방문하지 않은 정점 | 현재 정점과 next가 하나의 싸이클에 속함 |
finished[next] = true | 이런 경우는 없음 | 이미 모든 탐색이 끝난 정점. 현재 정점은 next가 싸이클 안에 있건 없건 절대 그 싸이클 안에 있을 수 없음 |
출처 : http://kks227.blog.me/220785731077
java구현
//BOJ 9466 public class DFS_isCycle { static int n, S[], cnt; //학생들의 수, 선택된 학생들의 번호 , 싸이클에 속하는 정점의 개수 static boolean visited[], finished[]; public static void main(String[] args) throws Exception { // TODO Auto-generated method stub BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); StringTokenizer st; int T = Integer.parseInt(br.readLine()); for(int i=1; i<=T; i++){ n = Integer.parseInt(br.readLine()); st = new StringTokenizer(br.readLine()); S = new int[n+1]; for(int j = 1; j<=n; j++){ S[j] = Integer.parseInt(st.nextToken()); } visited = new boolean[n+1]; finished = new boolean[n+1]; //각 컴포넌트에 대해 DFS시작 cnt = 0; for(int k=1; k<=n; k++){ if(!visited[k]) dfs(k); } System.out.println(n-cnt); } } private static void dfs(int curr) { visited[curr] = true; int next = S[curr]; if(visited[next]){ if(!finished[next]){ for(int temp = next; temp!=curr; temp=S[temp]) cnt++; cnt++;//자기 자신 } }else dfs(next); finished[curr] = true; } }
http://kks227.blog.me 블로그를 참고하여 구현하였습니다.
'개발레시피 > └ Algorithm' 카테고리의 다른 글
[그래프/개념] 최소 스패닝 트리(Minimum Spanning Tree), 크루스칼 알고리즘 (0) | 2017.11.16 |
---|---|
[그래프/개념] 다익스트라 알고리즘(Dijkstra's Algorithm) , 최단경로구하기 (0) | 2017.11.13 |
[그래프/개념] DFS(깊이우선탐색)과 BFS(너비우선탐색) (0) | 2017.05.28 |
[자료구조/문제] 구간합, BOJ 2042, Binary Indexed Tree (0) | 2017.05.28 |
[자료구조/문제] 중앙값(Median) 구하기, BOJ 2696, Heap (0) | 2017.05.27 |
Comments