문제 링크 : https://www.acmicpc.net/problem/2533
트리에서의 다이나믹 프로그래밍문제. 다행히 난 아직 다이나믹 프로그래밍은 점화식을 설정하는 게 중요하다는 걸 기억하고 있다.. 이 문제에서 dp[x] 는 이렇게 설정했다.
dp[X] = (X를 루트노드로 갖는 서브 트리에서, 최소 얼리 어덥터의 수)
점화식은 아래처럼 세울 수 있었다.
if (dp[X] 의 child 가 모두 어덥터라면)
dp[X] = dp[child1] + dp[child2] + .. dp[child마지막]
else (dp[X] 의 child 가 모두 어덥터인 것은 아니라면)
// -> X도 어덥터가 되어야 하므로 1을 더해준다.
dp[X] = dp[child1] + dp[child2] + .. dp[child마지막] + 1
dfs 로 모든 트리를 탐색했고, dfs 의 리턴값은 본인이 어덥터가 되는지로 설정했다. 그리고 이 문제의 경우, 탐색을 어떤 노드에서부터 시작하던지 상관 없기 때문에 1번 노드부터 탐색을 시작했다.
import sys sys.setrecursionlimit(10**6) N = int(sys.stdin.readline()) tree = [[] for _ in range(N+1)] # dp[x] = [n, q] # n = x를 루트로 하는 서브트리에서의 최소 어덥터 수 # q = 루트 x가 어덥터인지 여부 dp = [-1] * (N+1) visit = [False] * (N+1) in_degree = [0] * (N+1) root = 1 for _ in range(N-1): u, v = map(int, sys.stdin.readline().split()) tree[u].append(v) tree[v].append(u) in_degree[v] += 1 # 리턴 값은 현재 노드가 어댑터가 될 것인지 def dfs(node): visit[node] = True # 만약 현재 노드가 리프라면 if not tree[node]: dp[node] = 0 return False # 현재 노드가 리프가 아니라면 all_children_is_adapter = True dp[node] = 0 for child in tree[node]: if not visit[child]: result = dfs(child) dp[node] += dp[child] if not result: all_children_is_adapter = False if all_children_is_adapter: return False else: dp[node] += 1 return True dfs(root) print(dp[root])