백준: 효율적인 해킹

풀이
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main {
	static int N, M;
	static ArrayList <Integer>[] arr;
	static boolean isVisited[];
	static int max;
	static int cntArr[];
	
	
	static void BFS(int start) {
		Queue <Integer> que = new ArrayDeque<Integer>();
		que.add(start);
		isVisited[start] = true;
		
		while(!que.isEmpty()) {
			int now = que.poll();
			for (int i : arr[now]) {
				if (isVisited[i]) 
				    continue;
				cntArr[i]++; // i가 해킹할 수 있는 숫자 증가
				isVisited[i] = true;
				que.add(i);
			}
		}
	}
	
	public static void main(String[] args) throws IOException {
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(bf.readLine());
		
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());
		
		isVisited = new boolean[N+1];
		cntArr = new int[N+1];
		
		// record trust relationship
		// trust list 담을 array 생성
		arr = new ArrayList[N+1];
		for (int i=0; i<N+1; i++) 
		    arr[i] = new ArrayList <Integer>();
		
		for (int i=0; i<M; i++) {
			st = new StringTokenizer(bf.readLine());
			int a = Integer.parseInt(st.nextToken());
			int b = Integer.parseInt(st.nextToken());
			arr[a].add(b); // at index a, exists b because ... a trusts b, arr is like a trust list
		}
		
		// 1번부터 N번까지 search
		for (int i=1; i<N+1; i++) {
			isVisited = new boolean[N+1]; // reset the isVisited boolean array
			BFS(i);
		}
		
		// 해킹할 수 있는 최댓값 찾기
		for (int i=1; i<N+1; i++) {
			if (max<cntArr[i]) 
			    max = cntArr[i];
		}
		
		// 최댓값인 컴퓨터 출력
		for (int i=1; i<N+1; i++) {
		    if (max == cntArr[i]) {
		        System.out.print(i+" ");
		    }
		        
		}
	}
}