15681번: 트리와 쿼리
문제 )
간선에 가중치와 방향성이 없는 임의의 루트 있는 트리가 주어졌을 때, 아래의 쿼리에 답해보도록 하자.
정점 U를 루트로 하는 서브트리에 속한 정점의 수를 출력한다.
만약 이 문제를 해결하는 데에 어려움이 있다면, 하단의 힌트에 첨부한 문서를 참고하자.
입력 :
트리의 정점의 수 N과 루트의 번호 R, 쿼리의 수 Q가 주어진다. (2 ≤ N ≤ 105, 1 ≤ R ≤ N, 1 ≤ Q ≤ 105)
이어 N-1줄에 걸쳐, U V의 형태로 트리에 속한 간선의 정보가 주어진다. (1 ≤ U, V ≤ N, U ≠ V)
이는 U와 V를 양 끝점으로 하는 간선이 트리에 속함을 의미한다.
이어 Q줄에 걸쳐, 문제에 설명한 U가 하나씩 주어진다. (1 ≤ U ≤ N)
입력으로 주어지는 트리는 항상 올바른 트리임이 보장된다.
출력 :
Q줄에 걸쳐 각 쿼리의 답을 정수 하나로 출력한다.
풀이)
풀이는 코드에 같이 적어 놓았다.
트리의 부모찾기 + dp라고 생각하면 될 듯 하다.
기본적으로 각 노드들은 1의 크기를 가지고 있고,
자신이 가지고 있는 자식들의 수가 많을 수록 크기가 커지게 된다.
따라서 루트 노드로부터 출발해 각 노드들의 크기를 sz 리스트에 저장하게 되면,
이 문제의 답이 나온다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
import sys
sys.setrecursionlimit(1 << 30)
# 트리의 부모찾기 베이스
def dfs(cur, prv):
# 자기 자신의 size는 일단 1을 갖는다.
sz[cur] = 1
for nxt in li[cur]:
# 앞으로 갈 곳이 이전에 갔던 곳이라면 가지 않음.
if nxt == prv:
continue
# sz의 크기는 서브트리의 크기가 된다.
sz[cur] += dfs(nxt, cur)
# dp의 탑다운을 생각하면 편함.
return sz[cur]
# 기본값들 입력받기
n, r, q = map(int, sys.stdin.readline().strip().split())
# 방향성이 없는 트리 생성
li = [[] for i in range(n + 1)]
for i in range(n - 1):
a, b = map(int, sys.stdin.readline().strip().split())
li[a].append(b)
li[b].append(a)
# dp를 위해 각 서브트리의 사이즈를 기록할 sz 리스트
sz = [0 for i in range(n + 1)]
# 루트트리를 기준으로 dfs
dfs(r, -1)
# 주어지는 각 쿼리에 따라 size를 출력한다.
for i in range(q):
u = int(sys.stdin.readline().strip())
print(sz[u])
|
cs |
출처 : https://www.acmicpc.net/problem/15681
15681번: 트리와 쿼리
트리의 정점의 수 N과 루트의 번호 R, 쿼리의 수 Q가 주어진다. (2 ≤ N ≤ 105, 1 ≤ R ≤ N, 1 ≤ Q ≤ 105) 이어 N-1줄에 걸쳐, U V의 형태로 트리에 속한 간선의 정보가 주어진다. (1 ≤ U, V ≤ N, U ≠ V)
www.acmicpc.net
'Develop > 백준 (python)' 카테고리의 다른 글
[백준] 15900번: 나무 탈출 (python) (0) | 2022.04.26 |
---|---|
[백준] 6064번: 카잉 달력 (python) (0) | 2022.04.18 |
[백준] 18870번: 좌표압축 (python) (0) | 2022.04.16 |
[백준] 5430번: AC (python) (0) | 2022.04.13 |
[백준] 1927번: 최소 힙 (python) (0) | 2022.04.13 |