https://www.acmicpc.net/problem/9466

 

9466번: 텀 프로젝트

이번 가을학기에 '문제 해결' 강의를 신청한 학생들은 텀 프로젝트를 수행해야 한다. 프로젝트 팀원 수에는 제한이 없다. 심지어 모든 학생들이 동일한 팀의 팀원인 경우와 같이 한 팀만 있을

www.acmicpc.net

문제풀이

DFS 문제였습니다.

문제조건에

- T

- n (2 ≤ n ≤ 100,000)

일반 BFS로 모든 경우를 다 돌면서 처리를 할경우 O(N^2) 으로  T * (100,000) * (100,000) 으로 최악의 경우에 100억 * T 의 시간이 걸립니다.

 

 

그렇기에 Visited 방문 배열과 CycleFinished 사이클을 경험 배열을 선언하여

, CycleFinished를 경험했다면 DFS 자체를 돌지 못하게 처리함으로써 시간초과를 줄일 수 있습니다.

또한, 그 와중에 방문처리는 초기화 시킴으로써, 사이클 검사를 올바르게 할 수 있도록 처리해야합니다.

 

자세한 설명은 주석처리해두었습니다.

 

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
	public static int T, N, count= 0;
	public static int[] map;
	public static boolean[] visited, cyclefinished;
	public static int result = 0;
    public static void main(String[] args) throws IOException{
    	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    	
    	StringTokenizer st = new StringTokenizer(br.readLine());
    	T = Integer.parseInt(st.nextToken());
    	
    	while(T > 0) {
	       	N = Integer.parseInt(br.readLine());
	     	map = new int[N+1];
	     	visited = new boolean[N+1];
	     	cyclefinished = new boolean[N+1];
	     	count = 0;

     		st = new StringTokenizer(br.readLine());
	     	for(int i=1;i<=N;i++) {
     			map[i] = Integer.parseInt(st.nextToken());
	     	}
	     	
	     	for(int i=1; i<=N;i++) {
	     		if(cyclefinished[i]) continue;  //사이클을 한번이라도 검사에 넣었는데 실패햇다면 사이클이 불가능함
	     		DFS(i);
	     	}
	     	T--;
	     	System.out.println(N - count);
    	}

    	
    }
    
    public static void DFS(int now) {
    	if(visited[now]) { //Cycle에서 두번쨰 방문이라면 이미 Cycle 에 포함되었음
    		cyclefinished[now] = true; //Cycle 검사가 끝남
    		count++; //Cycle에 포함되었으므로  count++
    	}
    	else if(visited[now] == false){ //첫방문인경우
    		visited[now] = true; //방문처리
    	}
    	
    	int next = map[now];
    	if(!cyclefinished[next]) { //아직 Cycle 검사가 안끝났다면 계속해서 DFS를 들어갑니다.
    		DFS(next);
    	}
    	
    	visited[now] = false; //방문처리를 종료
    	cyclefinished[now] = true; //만약 사이클에 들어가지 않았다면 더이상 사이클검사를 해도 의미가 없으므로 사이클을 했다는 flag가 남겨져있다고 처리
    	
    }
    
}

+ Recent posts