새소식

Computer Science/코딩테스트 문제 풀이

⭐⭐⭐⭐[코드트리] 트리 파악

  • -

https://www.codetree.ai/missions/9/problems/identifying-the-tree/description

 

코드트리 | 코딩테스트 준비를 위한 알고리즘 정석

국가대표가 만든 코딩 공부의 가이드북 코딩 왕초보부터 꿈의 직장 코테 합격까지, 국가대표가 엄선한 커리큘럼으로 준비해보세요.

www.codetree.ai

문제

트리의 모든 리프 노드에는 말이 정확히 하나씩 놓여있습니다. 이제 a와 b가 서로 번갈아가며 한 번에 말을 하나씩 옮기는 게임을 하려고 합니다. 게임의 방식은 다음과 같습니다.

  • 차례가 되면 존재하는 말 중 아무거나 하나를 골라 그 말이 놓여있던 노드의 부모 노드로 말을 옮깁니다.
  • 한 노드에는 여러개의 말이 존재할 수 있습니다.
  • 루트 노드에 말이 도착한다면 즉시 그 말을 제거합니다. 여기서 루트 노드는 번 입니다.
  • 더 이상 옮길 말이 없는 상태에서 차례가 돌아온 사람의 패배입니다.

a가 먼저 시작하며 a, b 모두 최선을 다해 게임을 진행한다고 했을 때, 주어진 트리에서 a가 승리할 수 있는지 판단하는 프로그램을 작성해보세요.

 

입력 형식

첫 번째 줄에 트리 노드의 개수 이 주어집니다.

두 번째 줄부터 개의 줄에 각각 걸쳐 간선으로 연결된 두 개의 노드 번호가 공백을 두고 차례대로 출력됩니다.

  •  트리의 노드 번호 

출력 형식

주어진 트리에서 a가 승리할 수 있다면 을, 승리할 수 없다면 을 출력하세요.

 

입출력 예제

예제1

입력:

5
1 2
1 3
3 4
4 5

 

출력:

0

 


이 문제는 시뮬레이션 처럼 푸는 것이 아니라
모든 리프노드와 루트노드까지의 거리를 모두 구해 그 합이 홀수 인지 짝수 인지 알아보는 문제이다.

루트노드와 모든 리프노드의 말까지 거리의 합이 S라고 하자
a가 한턴 진행하면 말 하나가 위로 올라가고 S는 -1만큼 줄어든다.
b가 한턴 진행하면 어떤 말을 하나 선택하든 역시 말 하나가 위로 올라가고 S는 -1만큼 줄어든다.
이러한 과정을 반복하다가 S가 최초로 0이 되는 턴에 말을 움직여야 하는 사람이 진다.

-> 따라서 루트노드에서 모든 리프노드까지의 거리를 구해야한다.

 

import sys
sys.stdin=open('input.txt', 'r')

sys.setrecursionlimit(100_000)

# DFS를 통해 리프노드와 리프노드의 깊이를 탐색합니다.
def DFS(x):
    global S
    
    is_leaf=True
    for y in graph[x]:
        if visited[y]:          # 이미 방문한 노드는 스킵합니다.
            continue
        is_leaf=False           # 하나라도 자식 노드가 있다면 리프 노드가 아닙니다.
        visited[y]=True         # 방문 체크
        depth[y] = depth[x]+1   # root로부터의 거리를 갱신합니다.
        DFS(y)
        
    if is_leaf:                 # 리프노드라면, 해당 노드의 깊이를 더합니다.
        S += depth[x]

if __name__=="__main__":
    n = int(input())
    graph=[[] for _ in range(n+1)]
    visited = [False]*(n+1)
    depth = [0]*(n+1)                   # 루트노드와 리프노드간의 깊이(거리)를 저장
    for _ in range(n-1):
        a,b=map(int, input().split())
        graph[a].append(b)
        graph[b].append(a)
    
    
    S=0                                 # 리프노드 깊이의 총합
    root = 1
    visited[root]=True 
    DFS(root)                           # DFS를 통해 리프노드와 리프노드의 깊이를 탐색합니다.
    
    # 모든 리프노드의 깊이의 합이 짝수인지 홀수인지 판단해 정답을 출력합니다.
    if S%2==1:
        print(1)
    else:
        print(0)
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.