Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

파이썬으로 트리에서 거리가 정확히 k인 고유한 정점 쌍 개수 구하기

문제 소개

정수 kn개의 노드로 이루어진 트리가 주어졌을 때, 서로 다른 두 정점 사이의 거리가 정확히 k가 되는 고유한 정점 쌍의 개수를 세는 것이 이 글의 목표입니다.

예를 들어 k = 2이고 다음과 같은 트리가 주어진다고 가정해 보겠습니다.

파이썬으로 트리에서 거리가 정확히 k인 고유한 정점 쌍 개수 구하기

이 트리에서 거리가 정확히 2인 정점 쌍은 총 4개이므로, 기대되는 출력값은 4입니다.

알고리즘 접근 방법

이 문제는 깊이 우선 탐색(DFS)을 활용하면 효율적으로 해결할 수 있습니다. 핵심 아이디어는 각 정점 v에 대해 "v로부터 거리가 d인 정점의 개수"를 저장하고, 자식 서브트리의 정보를 부모 정점으로 병합하는 과정에서 거리가 k가 되는 쌍을 세는 것입니다.

사용되는 주요 변수와 함수는 다음과 같습니다.

  • N = 5005: 처리 가능한 최대 노드 수
  • graph: 크기 N의 인접 리스트
  • vertex_count: 각 정점에서 거리별로 도달 가능한 정점 수를 저장하는 2차원 배열
  • res: 조건을 만족하는 정점 쌍의 개수(결과값)

insert_edge(x, y) 함수

x와 y 사이에 무방향 간선을 연결합니다. graph[x]의 끝에 y를 추가하고, graph[y]의 끝에 x를 추가합니다.

dfs(v, parent) 함수

  1. vertex_count[v][0]을 1로 설정합니다. 자기 자신까지의 거리는 0이기 때문입니다.
  2. v의 모든 인접 정점 i에 대해, i가 부모가 아니라면 다음 작업을 수행합니다.
    • dfs(i, v)를 호출하여 자식 서브트리를 먼저 탐색합니다.
    • j를 1부터 k+1까지 순회하며 res += vertex_count[i][j-1] * vertex_count[v][k-j]를 계산합니다. 자식 서브트리 안의 정점과 기존에 누적된 정점을 잇는 경로 길이가 정확히 k가 되는 쌍을 세는 단계입니다.
    • j를 1부터 k+1까지 순회하며 vertex_count[v][j] += vertex_count[i][j-1]로 자식 서브트리의 거리별 정보를 현재 정점에 병합합니다.

구현 예제

다음은 위 알고리즘을 파이썬으로 구현한 전체 코드입니다.

N = 5005
graph = [[] for i in range(N)]
vertex_count = [[0 for i in range(505)] for i in range(N)]
res = 0

def insert_edge(x, y):
    graph[x].append(y)
    graph[y].append(x)

def dfs(v, parent):
    global res
    vertex_count[v][0] = 1
    for i in graph[v]:
        if (i != parent):
            dfs(i, v)
            for j in range(1, k + 1):
                res += vertex_count[i][j - 1] * vertex_count[v][k - j]
            for j in range(1, k + 1):
                vertex_count[v][j] += vertex_count[i][j - 1]

k = 2
insert_edge(1, 2)
insert_edge(2, 3)
insert_edge(3, 4)
insert_edge(2, 5)
dfs(1, 0)
print(res)

입력

k = 2
insert_edge(1, 2)
insert_edge(2, 3)
insert_edge(3, 4)
insert_edge(2, 5)

출력

4

마무리

이 알고리즘은 각 간선을 한 번씩 처리하면서 거리별 정점 개수를 병합하므로, 전체 시간 복잡도는 O(n × k)입니다. 트리 문제에서 자식 서브트리의 정보를 부모 정점으로 병합하는 이러한 패턴은 다양한 경로 계산 문제에 널리 응용되므로, 잘 익혀두면 코딩 테스트나 알고리즘 문제 해결에 큰 도움이 됩니다.