알고리즘/BAEKJOON

[백준] 15681 트리와 쿼리 (Java)

kyeee2 2022. 5. 20. 22:13

[15681 트리와 쿼리]

난이도: 골드5

 

15681번: 트리와 쿼리

트리의 정점의 수 N과 루트의 번호 R, 쿼리의 수 Q가 주어진다. (2 ≤ N ≤ 105, 1 ≤ R ≤ N, 1 ≤ Q ≤ 105) 이어 N-1줄에 걸쳐, U V의 형태로 트리에 속한 간선의 정보가 주어진다. (1 ≤ U, V ≤ N, U ≠ V)

www.acmicpc.net

문제

 
입력

출력


[아이디어]

처음에는 트리를 생성해준 뒤 쿼리 개수만큼 정점의 수를 구했는데, 시간 초과가 났다. 그래서 문제 아래 있는 힌트대로 정점의 개수를 구하는 함수를 구현해주었다.

 


[JAVA 코드]

import java.io.*;
import java.util.*;

public class Main {
	
	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	static StringBuilder output = new StringBuilder();
	static StringTokenizer tokens;

	static int N, M, R;
	static int [] size; // 서브 트리의 정점 수
	static List<List<Integer>> graph = new ArrayList<>(); // 양방향 그래프
	static List<List<Integer>> tree = new ArrayList<>();  // 단방향 트리

	public static void main(String[] args) throws IOException {
		tokens = new StringTokenizer(br.readLine());
		N = Integer.parseInt(tokens.nextToken());
		R = Integer.parseInt(tokens.nextToken());
		M = Integer.parseInt(tokens.nextToken());
		
		for(int i = 0; i <= N; i++) {
			graph.add(new ArrayList<>());
			tree.add(new ArrayList<>());
		}
		
		for(int i = 0; i < N - 1; i++) {
			tokens = new StringTokenizer(br.readLine());
			int v1 = Integer.parseInt(tokens.nextToken());
			int v2 = Integer.parseInt(tokens.nextToken());
			
			// 우선 양방향으로 정해주기
			graph.get(v1).add(v2);
			graph.get(v2).add(v1);
		}
		
		makeTree();

		size = new int [N + 1];
		countSubTree(R);
		
		// 쿼리 실행
		for(int i = 0; i < M; i++) {
			int r = Integer.parseInt(br.readLine()); // 서브 트리의 루트
			
			output.append(size[r] + "\n");
		}
		System.out.println(output);
	}

	// 트리 만들어주기
	private static void makeTree() {
		Queue<Integer> Q = new LinkedList<>();
		boolean [] visited = new boolean [N + 1];
		
		// 루트 넣어주기
		Q.offer(R);
		visited[R] = true;
		
		while(!Q.isEmpty()) {
			int ver = Q.poll();
			
			for(int i = 0; i < graph.get(ver).size(); i++) {
				int v = graph.get(ver).get(i);
				
				if(visited[v]) continue;
				
				tree.get(ver).add(v);
				Q.offer(v);
				visited[v] = true;
			}
		}
	}

	// 서브 트리의 정점의 수
	private static void countSubTree(int root) {
		size[root] = 1;
		for(int ver: tree.get(root)) {
			countSubTree(ver);
			size[root] += size[ver];
		}
	}

}