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
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
  | // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
struct Solver {
    int n, q, r;
    vector<vector<int>> adj;
    vector<int> tin, tout, depth, subSize;
    vector<vector<int>> up;
    int LOG;
    int timer;
    void build(int root = 1) {
        LOG = 1;
        while ((1 << LOG) <= n) ++LOG;
        up.assign(LOG, vector<int>(n + 1, 0));
        tin.assign(n + 1, 0);
        tout.assign(n + 1, 0);
        depth.assign(n + 1, 0);
        subSize.assign(n + 1, 0);
        timer = 0;
        struct Frame { int u, p; bool exit; };
        vector<int> parent0(n + 1, 0);
        vector<char> visited(n + 1, 0);
        stack<Frame> st;
        st.push({root, 0, false});
        parent0[root] = 0;
        depth[root] = 0;
        while (!st.empty()) {
            auto cur = st.top(); st.pop();
            int u = cur.u, p = cur.p;
            if (!cur.exit) {
                if (visited[u]) continue;
                visited[u] = 1;
                tin[u] = ++timer;
                st.push({u, p, true});
                for (int v : adj[u]) if (v != p) {
                    parent0[v] = u;
                    depth[v] = depth[u] + 1;
                    st.push({v, u, false});
                }
            } else {
                int total = 1;
                for (int v : adj[u]) if (v != p) total += subSize[v];
                subSize[u] = total;
                tout[u] = ++timer;
            }
        }
        up[0] = parent0;
        for (int k = 1; k < LOG; ++k) {
            for (int v = 1; v <= n; ++v) {
                int mid = up[k - 1][v];
                up[k][v] = mid ? up[k - 1][mid] : 0;
            }
        }
    }
    inline bool isAncestor(int a, int b) const {
        return tin[a] <= tin[b] && tout[b] <= tout[a];
    }
    int lift(int u, int k) const {
        for (int i = 0; i < LOG && u; ++i) {
            if (k & (1 << i)) u = up[i][u];
        }
        return u;
    }
    long long answerFor(int u) {
        if (u == r) return n;
        if (isAncestor(u, r)) {
            int diff = depth[r] - depth[u];
            int v = lift(r, diff - 1); // child of u on path to r
            return n - subSize[v];
        }
        return subSize[u];
    }
    void run() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int T; 
        if (!(cin >> T)) return;
        for (int tc = 1; tc <= T; ++tc) {
            cin >> n >> q >> r;
            adj.assign(n + 1, {});
            for (int i = 0; i < n - 1; ++i) {
                int a, b; cin >> a >> b;
                adj[a].push_back(b);
                adj[b].push_back(a);
            }
            build(1);
            cout << "Case #" << tc << ":\n";
            for (int i = 0; i < q; ++i) {
                int s, u; cin >> s >> u;
                if (s == 0) r = u;
                else cout << answerFor(u) << '\n';
            }
        }
    }
};
int main() {
    Solver().run();
    return 0;
}
  |