티스토리 뷰

BOJ

[BOJ 15681] 트리와 쿼리

gcmango 2021. 5. 5. 14:34

문제

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

 


풀이

트리DP를 사용합니다.

트리가 주어졌을 때, 배열 \(dp\)를 다음과 같이 정의할 수 있습니다:

 

\(dp[i]:\) \(i\)를 루트로 하는 서브트리에 속한 정점의 수.

 

트리를 순회하면서 \(i\)의 자식 노드들을 \(c_{1}, c_{2}, c_{3}, ... , c_{m}\)이라고 할 때, \(dp[i]\)에 다음 값을 저장합니다:

$$dp[i] = 1 + \sum_{j = 1}^{m} dp[c_{j}]$$

각 쿼리마다 \(U\)가 주어졌을 때 \(dp[U]\)를 출력하면 됩니다.

 


코드

#include <bits/stdc++.h>
using namespace std;

int N, R, Q;
vector<vector<int>> arr;
vector<int> dp;

int solve(int cur, int pnode) {
    for (auto node : arr[cur])
        if (node != pnode)
            dp[cur] += solve(node, cur);

    return dp[cur];
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> N >> R >> Q;
    arr.resize(N + 1);
    dp.resize(N + 1, 1);

    for (int i = 0; i < N - 1; ++i) {
        int a, b;
        cin >> a >> b;
        arr[a].push_back(b);
        arr[b].push_back(a);
    }

    solve(R, 0);

    while (Q--) {
        int query;
        cin >> query;
        cout << dp[query] << "\n";
    }

    return 0;
}

'BOJ' 카테고리의 다른 글

[BOJ 3584] 가장 가까운 공통 조상  (0) 2021.05.08
[BOJ 1949] 우수 마을  (0) 2021.05.05
[BOJ 11438] LCA 2  (0) 2021.05.04
[BOJ 10942] 팰린드롬?  (0) 2021.05.03
[BOJ 11054] 가장 긴 바이토닉 부분 수열  (0) 2021.05.03
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/09   »
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
글 보관함