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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
  | // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int N;
    if (!(cin >> N)) return 0;
    vector<vector<int>> adj(N + 1);
    for (int i = 0; i < N - 1; ++i) {
        int x, y; cin >> x >> y;
        adj[x].push_back(y);
        adj[y].push_back(x);
    }
    int LOG = 1;
    while ((1 << LOG) <= N) ++LOG;
    vector<int> depth(N + 1, 0);
    vector<vector<int>> up(LOG, vector<int>(N + 1, 0));
    {
        queue<int> q;
        q.push(1);
        up[0][1] = 0;
        depth[1] = 0;
        vector<char> visited(N + 1, 0);
        visited[1] = 1;
        while (!q.empty()) {
            int u = q.front(); q.pop();
            for (int v : adj[u]) {
                if (!visited[v]) {
                    visited[v] = 1;
                    up[0][v] = u;
                    depth[v] = depth[u] + 1;
                    q.push(v);
                }
            }
        }
    }
    for (int k = 1; k < LOG; ++k) {
        for (int v = 1; v <= N; ++v) {
            int mid = up[k - 1][v];
            up[k][v] = (mid == 0 ? 0 : up[k - 1][mid]);
        }
    }
    auto lift = [&](int u, int k) {
        for (int i = 0; i < LOG && u; ++i) {
            if (k & (1 << i)) u = up[i][u];
        }
        return u;
    };
    auto lca = [&](int a, int b) {
        if (depth[a] < depth[b]) swap(a, b);
        a = lift(a, depth[a] - depth[b]);
        if (a == b) return a;
        for (int k = LOG - 1; k >= 0; --k) {
            if (up[k][a] != up[k][b]) {
                a = up[k][a];
                b = up[k][b];
            }
        }
        return up[0][a];
    };
    auto dist = [&](int a, int b) {
        int w = lca(a, b);
        return depth[a] + depth[b] - 2 * depth[w];
    };
    auto kthOnPath = [&](int u, int v, int k) {
        int w = lca(u, v);
        int du = depth[u] - depth[w];
        if (k <= du) return lift(u, k);
        int dv = depth[v] - depth[w];
        int upSteps = dv - (k - du);
        return lift(v, upSteps);
    };
    int Q; cin >> Q;
    while (Q--) {
        int a, b, c; cin >> a >> b >> c;
        int ab = lca(a, b);
        int bc = lca(b, c);
        int ca = lca(c, a);
        int s = ab;
        if (depth[bc] > depth[s]) s = bc;
        if (depth[ca] > depth[s]) s = ca;
        array<pair<int,int>,3> d = {{
            {dist(s, a), 0},
            {dist(s, b), 1},
            {dist(s, c), 2}
        }};
        sort(d.begin(), d.end());
        if (d[0].first == d[1].first) {
            if (d[2].first == d[1].first) {
                cout << s << '\n';
            } else {
                int diff = d[2].first - d[0].first;
                if (diff % 2) {
                    cout << -1 << '\n';
                } else {
                    int nodes[3] = {a, b, c};
                    int farNode = nodes[d[2].second];
                    int t = diff / 2;
                    int ans = kthOnPath(s, farNode, t);
                    cout << ans << '\n';
                }
            }
        } else {
            cout << -1 << '\n';
        }
    }
    return 0;
}
  |