Problem: cf1305_d
Difficulty: easy
Categories: graph
Time limit: 1000 ms, memory limit: 256 MB

This is an interactive problem.

After getting AC after 13 Time Limit Exceeded verdicts on a geometry problem, Kuroni went to an Italian restaurant to celebrate this holy achievement. Unfortunately, the excess sauce disoriented him, and he's now lost!

The United States of America can be modeled as a tree (why though) with $n$ vertices. The tree is rooted at vertex $r$, wherein lies Kuroni's hotel.

Kuroni has a phone app designed to help him in such emergency cases. To use the app, he has to input two vertices $u$ and $v$, and it'll return a vertex $w$, which is the lowest common ancestor of those two vertices.

However, since the phone's battery has been almost drained out from live-streaming Kuroni's celebration party, he could only use the app at most $\lfloor \frac{n}{2} \rfloor$ times. After that, the phone would die and there will be nothing left to help our dear friend! :(

As the night is cold and dark, Kuroni needs to get back, so that he can reunite with his comfy bed and pillow(s). Can you help him figure out his hotel's location?

Interaction

The interaction starts with reading a single integer $n$ ($2 \le n \le 1000$), the number of vertices of the tree.

Then you will read $n-1$ lines, the $i$-th of them has two integers $x_i$ and $y_i$ ($1 \le x_i, y_i \le n$, $x_i \ne y_i$), denoting there is an edge connecting vertices $x_i$ and $y_i$. It is guaranteed that the edges will form a tree.

Then you can make queries of type "? u v" ($1 \le u, v \le n$) to find the lowest common ancestor of vertex $u$ and $v$.

After the query, read the result $w$ as an integer.

In case your query is invalid or you asked more than $\lfloor \frac{n}{2} \rfloor$ queries, the program will print $-1$ and will finish interaction. You will receive a Wrong answer verdict. Make sure to exit immediately to avoid getting other verdicts.

When you find out the vertex $r$, print "! $r$" and quit after that. This query does not count towards the $\lfloor \frac{n}{2} \rfloor$ limit.

Note that the tree is fixed beforehand and will not change during the queries, i.e. the interactor is not adaptive.

After printing any query do not forget to print end of line and flush the output. Otherwise, you might get Idleness limit exceeded. To do this, use:

* fflush(stdout) or cout.flush() in C++;
* System.out.flush() in Java;
* flush(output) in Pascal;
* stdout.flush() in Python;
* see the documentation for other languages.

Example

Input

```
6
1 4
4 2
5 3
6 3
2 3

3

4

4
```

Output

```
? 5 6

? 3 1

? 1 2

! 4
```

Note

Note that the example interaction contains extra empty lines so that it's easier to read. The real interaction doesn't contain any empty lines and you shouldn't print any extra empty lines as well.

The image below demonstrates the tree in the sample test:

![](https://espresso.codeforces.com/df1619f848490908fe36e4d1a2431126f2b546c3.png)

Non-adaptive interactor (C++):
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

static long long queries = 0;
static long long query_limit = 0;

static void log_metrics() {
    try {
        tout << "queries=" << queries << "\n";
        tout << "query_limit=" << query_limit << "\n";
        tout.flush();
    } catch (...) {
        
    }
}

static void finish(TResult verdict, const string& msg) {
    log_metrics();
    quitf(verdict, "%s", msg.c_str());
}

static bool readIntFromCin(long long &x) {
    
    string s;
    if (!(cin >> s)) return false;
    if (s.empty()) return false;

    int i = 0;
    bool neg = false;
    if (s[i] == '+' || s[i] == '-') {
        neg = (s[i] == '-');
        i++;
    }
    if (i >= (int)s.size()) return false;

    long long val = 0;
    for (; i < (int)s.size(); i++) {
        if (s[i] < '0' || s[i] > '9') return false;
        int d = s[i] - '0';
        if (val > (LLONG_MAX - d) / 10) return false;
        val = val * 10 + d;
    }
    x = neg ? -val : val;
    return true;
}

struct LCA {
    int n = 0;
    int root = 1;
    int LOG = 0;
    vector<vector<int>> up;
    vector<int> depth;
    vector<vector<int>> g;

    LCA() = default;

    LCA(int n_, const vector<vector<int>>& g_, int root_) : n(n_), root(root_), g(g_) {
        LOG = 1;
        while ((1 << LOG) <= n) LOG++;
        up.assign(LOG, vector<int>(n + 1, 0));
        depth.assign(n + 1, 0);

        vector<int> parent(n + 1, 0);
        vector<int> vis(n + 1, 0);
        queue<int> q;
        q.push(root);
        vis[root] = 1;
        parent[root] = root;
        depth[root] = 0;

        while (!q.empty()) {
            int u = q.front();
            q.pop();
            for (int v : g[u]) {
                if (vis[v]) continue;
                vis[v] = 1;
                parent[v] = u;
                depth[v] = depth[u] + 1;
                q.push(v);
            }
        }

        for (int v = 1; v <= n; v++) {
            if (!vis[v]) {
                
                parent[v] = v;
                depth[v] = 0;
            }
            up[0][v] = parent[v];
        }
        for (int k = 1; k < LOG; k++) {
            for (int v = 1; v <= n; v++) {
                up[k][v] = up[k - 1][ up[k - 1][v] ];
            }
        }
    }

    int lift(int v, int dist) const {
        for (int k = 0; k < LOG; k++) {
            if (dist & (1 << k)) v = up[k][v];
        }
        return v;
    }

    int lca(int a, int b) const {
        if (a < 1 || a > n || b < 1 || b > n) return 0;
        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];
    }
};

int main(int argc, char** argv) {
    registerInteraction(argc, argv);
    atexit(log_metrics);

    int n = inf.readInt(2, 1000, "n");
    vector<pair<int,int>> edges;
    edges.reserve(max(0, n - 1));
    vector<vector<int>> g(n + 1);

    for (int i = 0; i < n - 1; i++) {
        int x = inf.readInt(1, n, "x_i");
        int y = inf.readInt(1, n, "y_i");
        if (x == y) finish(_fail, "Invalid hidden input: self-loop");
        edges.push_back({x, y});
        g[x].push_back(y);
        g[y].push_back(x);
    }

    int root = inf.readInt(1, n, "r");

    query_limit = n / 2;
    log_metrics(); 

    const long long hard_cap = max(200000LL, 10LL * query_limit);

    
    cout << n << "\n";
    for (auto [u, v] : edges) cout << u << " " << v << "\n";
    cout.flush();

    LCA solver(n, g, root);

    while (true) {
        string cmd;
        if (!(cin >> cmd)) finish(_pe, "Unexpected EOF (no final answer)");

        if (cmd == "?") {
            long long u_ll, v_ll;
            if (!readIntFromCin(u_ll) || !readIntFromCin(v_ll)) {
                finish(_pe, "Malformed query: expected '? u v'");
            }
            if (u_ll < 1 || u_ll > n || v_ll < 1 || v_ll > n) {
                cout << -1 << "\n";
                cout.flush();
                finish(_wa, "Invalid query vertices out of range");
            }

            queries++;
            if (queries > hard_cap) {
                finish(_pe, "Hard cap exceeded (too many queries)");
            }

            int u = (int)u_ll;
            int v = (int)v_ll;
            int w = solver.lca(u, v);
            if (w <= 0) {
                cout << -1 << "\n";
                cout.flush();
                finish(_wa, "Internal error computing LCA");
            }
            cout << w << "\n";
            cout.flush();
        } else if (cmd == "!") {
            long long ans_ll;
            if (!readIntFromCin(ans_ll)) finish(_pe, "Malformed answer: expected '! r'");
            if (ans_ll < 1 || ans_ll > n) finish(_wa, "Answer out of range");

            int ans = (int)ans_ll;
            if (ans == root) finish(_ok, "OK");
            finish(_wa, "Wrong root");
        } else {
            finish(_pe, "Unknown command (expected '?' or '!')");
        }
    }
}


Adaptive interactor (C++):

Test generator (C++):
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

static vector<pair<int,int>> makePath(int n) {
    vector<pair<int,int>> e;
    e.reserve(max(0, n - 1));
    for (int i = 1; i < n; i++) e.push_back({i, i + 1});
    return e;
}

static vector<pair<int,int>> makeStar(int n, int center = 1) {
    vector<pair<int,int>> e;
    e.reserve(max(0, n - 1));
    for (int i = 1; i <= n; i++) if (i != center) e.push_back({center, i});
    return e;
}

static vector<pair<int,int>> makeBinaryHeap(int n) {
    vector<pair<int,int>> e;
    e.reserve(max(0, n - 1));
    for (int i = 2; i <= n; i++) e.push_back({i / 2, i});
    return e;
}

static vector<pair<int,int>> makeBroom(int n, int spineLen) {
    spineLen = max(2, min(spineLen, n));
    vector<pair<int,int>> e;
    e.reserve(max(0, n - 1));
    for (int i = 1; i < spineLen; i++) e.push_back({i, i + 1});
    for (int v = spineLen + 1; v <= n; v++) e.push_back({spineLen, v});
    return e;
}

static vector<pair<int,int>> makeCaterpillar(int n, int spineLen) {
    spineLen = max(2, min(spineLen, n));
    vector<pair<int,int>> e;
    e.reserve(max(0, n - 1));
    for (int i = 1; i < spineLen; i++) e.push_back({i, i + 1});
    for (int v = spineLen + 1; v <= n; v++) {
        int attach = rnd.next(1, spineLen);
        e.push_back({attach, v});
    }
    return e;
}

static vector<pair<int,int>> makeTwoHubs(int n, int hubCount) {
    hubCount = max(2, min(hubCount, max(2, n)));
    vector<int> hubs;
    hubs.reserve(hubCount);
    for (int i = 1; i <= hubCount; i++) hubs.push_back(i);

    vector<pair<int,int>> e;
    e.reserve(max(0, n - 1));

    for (int i = 2; i <= hubCount; i++) e.push_back({1, i});

    for (int v = hubCount + 1; v <= n; v++) {
        int bias = rnd.next(1, 100);
        int parent;
        if (bias <= 70) {
            parent = hubs[rnd.next(0, (int)hubs.size() - 1)];
        } else {
            parent = rnd.next(1, v - 1);
        }
        e.push_back({parent, v});
    }
    return e;
}

static vector<pair<int,int>> makeRecursiveRandom(int n) {
    vector<pair<int,int>> e;
    e.reserve(max(0, n - 1));
    for (int v = 2; v <= n; v++) {
        int parent;
        int roll = rnd.next(1, 100);
        if (roll <= 60) {
            parent = rnd.next(1, max(1, v - 1));
        } else if (roll <= 85) {
            parent = max(1, v - 1);
        } else {
            parent = 1;
        }
        e.push_back({parent, v});
    }
    return e;
}

static vector<vector<int>> buildAdj(int n, const vector<pair<int,int>>& edges) {
    vector<vector<int>> g(n + 1);
    for (auto [u, v] : edges) {
        g[u].push_back(v);
        g[v].push_back(u);
    }
    return g;
}

static int farthestFrom(int start, const vector<vector<int>>& g, vector<int>* parentOut = nullptr) {
    int n = (int)g.size() - 1;
    vector<int> dist(n + 1, -1), parent(n + 1, -1);
    queue<int> q;
    q.push(start);
    dist[start] = 0;
    parent[start] = 0;
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (int v : g[u]) if (dist[v] == -1) {
            dist[v] = dist[u] + 1;
            parent[v] = u;
            q.push(v);
        }
    }
    int best = start;
    for (int i = 1; i <= n; i++) {
        if (dist[i] > dist[best]) best = i;
    }
    if (parentOut) *parentOut = parent;
    return best;
}

static int pickAdversarialRoot(int n, const vector<pair<int,int>>& edges, long long seed) {
    auto g = buildAdj(n, edges);
    int a = farthestFrom(1, g);
    vector<int> parent;
    int b = farthestFrom(a, g, &parent);
    (void)parent;
    if (seed % 2 == 0) return a;
    return b;
}

static vector<int> makePermutation(int n) {
    vector<int> p(n + 1);
    for (int i = 1; i <= n; i++) p[i] = i;
    for (int i = 1; i <= n; i++) {
        int j = rnd.next(i, n);
        swap(p[i], p[j]);
    }
    return p;
}

int main(int argc, char** argv) {
    registerGen(argc, argv, 1);

    string mode = opt<string>("mode", "non");
    int maxn = opt<int>("n", 1000);
    int permuteLabels = opt<int>("permute", 1);

    long long seed = 1;
    if (argc >= 2) seed = atoll(argv[1]);

    int n;
    vector<pair<int,int>> edges;
    int root = 1;

    if (seed == 1) {
        n = 2;
        edges = {{1, 2}};
        root = 1;
        permuteLabels = 0;
    } else if (seed == 2) {
        n = min(1000, maxn);
        edges = makePath(n);
        root = 1;
        permuteLabels = 0;
    } else if (seed == 3) {
        n = min(1000, maxn);
        edges = makeBinaryHeap(n);
        root = n;
        permuteLabels = 0;
    } else {
        int hi = min(1000, maxn);
        int lo = max(2, hi - 30);
        n = rnd.next(lo, hi);

        string shape = opt<string>("shape", "auto");
        if (shape == "auto") {
            int pick = rnd.next(1, 100);
            if (pick <= 20) shape = "path";
            else if (pick <= 35) shape = "broom";
            else if (pick <= 55) shape = "caterpillar";
            else if (pick <= 75) shape = "twohubs";
            else if (pick <= 90) shape = "binary";
            else shape = "random";
        }

        if (shape == "path") {
            edges = makePath(n);
        } else if (shape == "star") {
            edges = makeStar(n, 1);
        } else if (shape == "binary") {
            edges = makeBinaryHeap(n);
        } else if (shape == "broom") {
            int spineLen = rnd.next(max(2, (int)(0.55 * n)), max(2, (int)(0.85 * n)));
            edges = makeBroom(n, spineLen);
        } else if (shape == "caterpillar") {
            int spineLen = rnd.next(max(2, (int)(0.35 * n)), max(2, (int)(0.65 * n)));
            edges = makeCaterpillar(n, spineLen);
        } else if (shape == "twohubs") {
            int hubs = rnd.next(2, min(25, n));
            edges = makeTwoHubs(n, hubs);
        } else {
            edges = makeRecursiveRandom(n);
        }

        root = pickAdversarialRoot(n, edges, seed);
    }

    if (permuteLabels && n >= 3) {
        vector<int> p = makePermutation(n);
        for (auto &e : edges) {
            e.first = p[e.first];
            e.second = p[e.second];
        }
        root = p[root];
    }

    cout << n << "\n";
    for (auto [u, v] : edges) {
        cout << u << " " << v << "\n";
    }

    if (mode == "non") {
        cout << root << "\n";
        return 0;
    }

    if (mode == "adp") {
        int k = n;
        cout << k << "\n";
        for (int i = 1; i <= n; i++) {
            if (i > 1) cout << " ";
            cout << i;
        }
        cout << "\n";
        return 0;
    }

    quitf(_fail, "Unknown --mode '%s' (expected 'non' or 'adp')", mode.c_str());
}