[BOJ] Q2533 사회망 서비스(SNS)

Question

Language: Python

Difficulty: Gold 3

Tree 와 DP를 결합한 응용 문제이다.

자식 노드를 처리하면서 루트 노드까지의 dfs를 통해 처리를 이어나간다.

q2533

부모 노드와 자식 노드 관계에서

부모노드는 얼리어댑터가 되는 경우, 얼리어댑터가 되지 않는 경우로 나눠서 생각할 수 있다.

얼리어댑터가 되는 경우에는 자식 노드에 대해서 얼리어댑터가 없어도 상관이 없다. 따라서, 각각의 자식 노드에 대해서, 얼리어댑터인 경우와 얼리어댑터가 아닌 경우 중 작은 값을 선택해서 모든 자식 노드의 값들을 합한다.

dfs를 진행함에 있어, 얼리어댑터가 되는 경우와 얼리어댑터가 되지 않는 경우를 비교해서 작은 값을 반환한다.

dp[vertex][1]+=solution(child)

부모노드가 얼리어댑터가 되지 않는 경우에는, 모든 자식 노드가 얼리어댑터인 경우이다.

dp[vertex][0]+=dp[child][1]

주의점

visited 배열을 이용해서 노드 간의 재방문을 허용하지 않도록 하고, 트리와 같이 처리 될 수 있도록 한다.

Solution

import sys
def solution(vertex):
    global dp,visited

    visited[vertex]=True

    for child in graph[vertex]:
        #재방문을 하지 않도록 한다. --> 트리
        if visited[child]:
            continue
        #얼리어댑터가 되는 경우: 자식노드의 값중 작은 값을 취해서 더한다.
        dp[vertex][1]+=solution(child)
        #얼리어댑터가 되지 않는 경우, 자식노드가 얼리어댑터 인경우의 값들을 더한다.
        dp[vertex][0]+=dp[child][1]
    #dp[vertex][0]: 해당 노드가 얼리어댑터가 아닌 경우
    #dp[vertex][1]: 해당 노드가 얼리어댑터가 되는 경우
    #이 두 가지 중 작은 값을 반환한다. --> 이러한 작업은 모든 자식 노드에 대해서 실행한다.
    return min(dp[vertex])
    
if __name__ == "__main__":
    sys.setrecursionlimit(10**9)
    input = sys.stdin.readline 
    N=int(input())
    graph=[[] for _ in range(N+1)]
    visited=[False] * (N+1)
    for _ in range(N-1):
        v1,v2=map(int,input().split())
        graph[v1].append(v2)
        graph[v2].append(v1)
    
    dp=[[0,1] for _ in range(N+1)]
    
    print(solution(1))

댓글남기기