https://www.acmicpc.net/problem/2533
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
static int N;
static HashMap<Integer, LinkedList<Integer>> tree;
static boolean[] visited;
static int[][] dp;
static void input() {
Reader scanner = new Reader();
N = scanner.nextInt();
tree = new HashMap<>();
for(int node = 1; node <= N; node++) tree.put(node, new LinkedList<>());
for(int edge = 0; edge < N - 1; edge++) {
int node1 = scanner.nextInt(), node2 = scanner.nextInt();
tree.get(node1).add(node2);
tree.get(node2).add(node1);
}
}
static void solution() {
visited = new boolean[N + 1];
dp = new int[N + 1][2];
findEarlyAdaptor(1);
System.out.println(Math.min(dp[1][0], dp[1][1]));
}
static void findEarlyAdaptor(int node) {
visited[node] = true;
dp[node][0] = 0;
dp[node][1] = 1;
for(int n : tree.get(node)) {
if(!visited[n]) {
findEarlyAdaptor(n);
dp[node][0] += dp[n][1];
dp[node][1] += Math.min(dp[n][0], dp[n][1]);
}
}
}
public static void main(String[] args) {
input();
solution();
}
static class Reader {
BufferedReader br;
StringTokenizer st;
public Reader() {
br = new BufferedReader(new InputStreamReader(System.in));
}
String next() {
while(st == null || !st.hasMoreElements()) {
try {
st = new StringTokenizer(br.readLine());
} catch(IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
int nextInt() {
return Integer.parseInt(next());
}
}
}
만약 현재 탐색하고 있는 사람이 얼리아답터가 아니라면 그 사람과 이웃한 사람들은 모두 얼리아답터여야만 합니다.
만약 현재 탐색하고 있는 사람이 얼리아답터라면 이웃한 사람들은 얼리아답터일 수도 있고 그렇지 않을 수도 있습니다.
그렇기 때문에 우선 현재 탐색하고 있는 사람을 방문했다는 의미로 그 사람의 visited 값을 true로 변경합니다.
2차원 배열 dp를 이용하는데 이는 다음을 의미합니다.
우선 현재 탐색하고 있는 사람의 dp 배열의 초기값은 본인이 얼리어답터가 아니라면 0로, 본인이 얼리어답터라면 한 명이 존재하기 때문에 1로 합니다.
현재 탐색하고 있는 사람의 이웃한 사람들을 모두 확인하여 만약 그 사람이 아직 방문되지 않았다면 재귀를 통해 그 사람에 대해서도 탐색합니다.
모든 이웃한 사람을 탐색한 이후에 현재 탐색하고 있는 사람의 dp 배열의 값은 아래와 같습니다.