Problem: cf1534_h
Difficulty: medium
Categories: graph, game, data structures
Time limit: 4000 ms, memory limit: 256 MB

This is an interactive problem.

As he qualified for IOI this year, Little Ericyi was given a gift from all his friends: a tree of $n$ nodes!

On the flight to IOI Little Ericyi was very bored, so he decided to play a game with Little Yvonne with his new tree. First, Little Yvonne selects two (not necessarily different) nodes $a$ and $b$ on the tree (without telling Ericyi), and then gives him a hint $f$ (which is some node on the path from $a$ to $b$).

Then, Little Ericyi is able to ask the following question repeatedly:

* If I rooted the tree at node $r$ (Ericyi gets to choose $r$), what would be the Lowest Common Ancestor of $a$ and $b$?

Little Ericyi's goal is to find the nodes $a$ and $b$, and report them to Little Yvonne.

However, Little Yvonne thought this game was too easy, so before he gives the hint $f$ to Little Ericyi, he also wants him to first find the maximum number of queries required to determine $a$ and $b$ over all possibilities of $a$, $b$, and $f$ assuming Little Ericyi plays optimally. Little Ericyi defines an optimal strategy as one that makes the minimum number of queries. Of course, once Little Ericyi replies with the maximum number of queries, Little Yvonne will only let him use that many queries in the game.

The tree, $a$, $b$, and $f$ are all fixed before the start of the game and do not change as queries are made.

Interaction

First read a line containing the integer $n$ ($1 \le n \le 10^5$), the number of nodes in the tree.

The next $n−1$ lines describe Little Ericyi's tree. These lines contain two integers $u$ and $v$ ($1 \le u,v \le n$) denoting an edge between $u$ and $v$ ($u \neq v$). It is guaranteed that these edges form a tree.

After that you should output $k$, the maximum number of queries needed to determine $a$ and $b$ over all possibilities of $a$, $b$, and $f$ assuming Little Ericyi plays optimally. You should output end of line and flush the output after printing $k$.

After that read a line containing the integer $f$ ($1 \le f \le n$) — the hint: a node on the path from $a$ to $b$, inclusive.

After that, you can start making queries. You will be limited to making at most $k$ queries, where $k$ is the number you printed.

Each query is made in the format "? r", where $r$ is an integer $1 \le r \le n$ denoting the root node you want for the query.

You will then receive an integer $x$ ($1 \le x \le n$), the Lowest Common Ancestor of $a$ and $b$ if the tree was rooted at $r$.

When your program has found the nodes $a$, $b$, report the answer in the following format: "! a b", where $a$ and $b$ are the two hidden nodes and terminate your program normally immediately after flushing the output stream. You may output $a$ and $b$ in any order.

After printing a query do not forget to output end of line and flush the output. Otherwise, you will 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 documentation for other languages.

If at any point you make an invalid output or make more than $k$ queries, the interaction will terminate and you will receive a Wrong Answer verdict. An invalid output is defined as either an invalid query or a value of $k$ less than $0$ or greater than $n$.

Examples

Input

```
4
3 2
2 1
2 4

1

1

2

2
```

Output

```
3? 1? 2? 3! 4 1
```

Input

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

1

4

1

4
```

Output

```
3? 4? 1? 5! 1 4
```

Note

Here is the the tree from the first sample interaction. Nodes $a$ and $b$ are highlighted.![](https://espresso.codeforces.com/e9bafefcbcf2b756b5e46472466e179f5406956c.png) 

Notice that $a$ and $b$ can be output in any order.

Additionally, here are the answers to querying every single node $1,2,\ldots,n$ for your convenience:

* $1$: $1$
* $2$: $2$
* $3$: $2$
* $4$: $4$

\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_

Here is the the tree from the second sample interaction. Again, nodes $a$ and $b$ are highlighted.![](https://espresso.codeforces.com/bf6083420f0d88ebe3accc47e3008e805be9cc71.png) 

Lastly, here are the answers to querying every single node $1,2,\ldots,n$ (in example $2$) for your convenience:

* $1$: $1$
* $2$: $4$
* $3$: $1$
* $4$: $4$
* $5$: $4$

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 const long long HARD_CAP = 300000; 


void log_metrics() {
    try {
        
        
        tout << "queries=" << queries << endl;
        tout << "query_limit=" << query_limit << endl;
    } catch (...) {
        
    }
}


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




const int MAXN = 100005;
const int LOGN = 20;

int n;
vector<int> adj[MAXN];
int up[MAXN][LOGN];
int depth[MAXN];


void dfs(int u, int p, int d) {
    depth[u] = d;
    up[u][0] = p;
    for (int i = 1; i < LOGN; i++) {
        up[u][i] = up[up[u][i-1]][i-1];
    }
    for (int v : adj[u]) {
        if (v != p) dfs(v, u, d + 1);
    }
}


int get_lca(int u, int v) {
    if (depth[u] < depth[v]) swap(u, v);
    for (int i = LOGN - 1; i >= 0; i--) {
        if (depth[u] - (1 << i) >= depth[v]) {
            u = up[u][i];
        }
    }
    if (u == v) return u;
    for (int i = LOGN - 1; i >= 0; i--) {
        if (up[u][i] != up[v][i]) {
            u = up[u][i];
            v = up[v][i];
        }
    }
    return up[u][0];
}



int get_median(int a, int b, int r) {
    int x = get_lca(a, b);
    int y = get_lca(b, r);
    int z = get_lca(r, a);
    
    int res = x;
    if (depth[y] > depth[res]) res = y;
    if (depth[z] > depth[res]) res = z;
    return res;
}




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

    
    n = inf.readInt(1, 100000, "n");
    vector<pair<int, int>> edges;
    for (int i = 0; i < n - 1; i++) {
        int u = inf.readInt(1, n, "u");
        int v = inf.readInt(1, n, "v");
        edges.push_back({u, v});
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    
    
    
    int a_hidden = inf.readInt(1, n, "a");
    int b_hidden = inf.readInt(1, n, "b");
    int f_hidden = inf.readInt(1, n, "f");

    
    dfs(1, 1, 0);

    
    cout << n << endl;
    for (auto& e : edges) {
        cout << e.first << " " << e.second << endl;
    }
    cout.flush();

    
    
    string token;
    if (!(cin >> token)) {
        finish(_pe, "Expected k (max queries), found EOF");
    }
    
    
    try {
        size_t idx;
        long long k_val = stoll(token, &idx);
        if (idx != token.size()) finish(_pe, "Invalid format for k");
        if (k_val < 0 || k_val > n) finish(_wa, "k must be between 0 and n");
        query_limit = k_val;
    } catch (...) {
        finish(_pe, "Invalid format for k");
    }
    
    
    log_metrics();

    
    cout << f_hidden << endl; 
    
    
    while (true) {
        if (!(cin >> token)) {
            finish(_pe, "Unexpected EOF during query phase");
        }

        if (token == "!") {
            
            int ua, ub;
            if (!(cin >> ua >> ub)) {
                finish(_pe, "Expected two integers after '!'");
            }
            
            bool correct = (ua == a_hidden && ub == b_hidden) || (ua == b_hidden && ub == a_hidden);
            
            
            
            if (correct) {
                finish(_ok, "Found correct nodes");
            } else {
                finish(_wa, format("Expected {%d, %d}, found {%d, %d}", a_hidden, b_hidden, ua, ub));
            }
        } else if (token == "?") {
            
            int r;
            if (!(cin >> r)) {
                finish(_pe, "Expected integer r after '?'");
            }
            
            
            queries++;
            
            
            if (queries % 10 == 0) log_metrics();

            
            if (queries > HARD_CAP) {
                finish(_pe, "Hard query limit exceeded (potential infinite loop)");
            }

            
            if (r < 1 || r > n) {
                finish(_wa, "Query root r out of bounds");
            }

            
            int ans = get_median(a_hidden, b_hidden, r);
            cout << ans << endl; 
        } else {
            
            finish(_pe, "Expected '?' or '!', found: " + token);
        }
    }

    return 0;
}


Adaptive interactor (C++):
#include "testlib.h"
#include <bits/stdc++.h>

using namespace std;


static int n;
static vector<vector<int>> adj;
static vector<int> depth;
static vector<vector<int>> up;
static int LOG;
static long long queries = 0;
static long long query_limit = 0;



void log_metrics() {
    try {
        tout << "queries=" << queries << endl;
        tout << "query_limit=" << query_limit << endl;
    } catch (...) {
        
    }
}

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



void dfs(int u, int p, int d) {
    depth[u] = d;
    up[u][0] = p;
    for (int i = 1; i <= LOG; ++i) {
        up[u][i] = up[up[u][i - 1]][i - 1];
    }
    for (int v : adj[u]) {
        if (v != p) dfs(v, u, d + 1);
    }
}

int get_lca(int u, int v) {
    if (depth[u] < depth[v]) swap(u, v);
    for (int i = LOG; i >= 0; --i) {
        if (depth[u] - (1 << i) >= depth[v]) {
            u = up[u][i];
        }
    }
    if (u == v) return u;
    for (int i = LOG; i >= 0; --i) {
        if (up[u][i] != up[v][i]) {
            u = up[u][i];
            v = up[v][i];
        }
    }
    return up[u][0];
}




int get_median(int u, int v, int w) {
    int x = get_lca(u, v);
    int y = get_lca(v, w);
    int z = get_lca(u, w);
    int res = x;
    if (depth[y] > depth[res]) res = y;
    if (depth[z] > depth[res]) res = z;
    return res;
}


bool findPath(int u, int target, int p, vector<int>& path) {
    path.push_back(u);
    if (u == target) return true;
    for (int v : adj[u]) {
        if (v != p) {
            if (findPath(v, target, u, path)) return true;
        }
    }
    path.pop_back();
    return false;
}

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

    
    n = inf.readInt(1, 100000, "n");
    
    
    adj.resize(n + 1);
    vector<pair<int, int>> edge_list;
    for (int i = 0; i < n - 1; ++i) {
        int u = inf.readInt(1, n, "u");
        int v = inf.readInt(1, n, "v");
        ensuref(u != v, "Self loop edge %d-%d", u, v);
        adj[u].push_back(v);
        adj[v].push_back(u);
        edge_list.push_back({u, v});
    }

    
    LOG = 0;
    while ((1 << LOG) <= n) LOG++;
    depth.assign(n + 1, 0);
    up.assign(n + 1, vector<int>(LOG + 1));
    if (n > 0) dfs(1, 1, 0); 

    
    cout << n << endl;
    for (auto& e : edge_list) {
        cout << e.first << " " << e.second << endl;
    }
    cout.flush();

    
    long long k_usr;
    if (!(cin >> k_usr)) {
        finish(_wa, "Failed to read K from contestant");
    }
    if (k_usr < 0 || k_usr > n) {
        finish(_wa, format("Invalid K: %lld", k_usr));
    }
    query_limit = k_usr;
    
    
    
    
    int a, b, f_hint;
    inf.skipBlanks();
    if (!inf.eof()) {
        
        a = inf.readInt(1, n, "a");
        b = inf.readInt(1, n, "b");
        f_hint = inf.readInt(1, n, "f");
    } else {
        
        a = rnd.next(1, n);
        b = rnd.next(1, n);
        vector<int> path;
        findPath(a, b, 0, path);
        if (path.empty()) finish(_fail, "Path finding failed");
        f_hint = path[rnd.next(0, (int)path.size() - 1)];
    }

    
    cout << f_hint << endl;
    cout.flush();

    
    log_metrics();

    
    
    long long hard_cap = 200000; 
    if (query_limit > 0) hard_cap = max(hard_cap, query_limit * 10);

    while (true) {
        string type;
        if (!(cin >> type)) {
            finish(_wa, "Unexpected EOF awaiting query/answer");
        }

        if (type == "!") {
            int ans_a, ans_b;
            if (!(cin >> ans_a >> ans_b)) {
                finish(_wa, "Invalid answer format");
            }
            
            bool correct = (ans_a == a && ans_b == b) || (ans_a == b && ans_b == a);
            if (correct) {
                finish(_ok, format("Found {%d, %d} in %lld queries", a, b, queries));
            } else {
                finish(_wa, format("Wrong answer: expected {%d, %d}, found {%d, %d}", a, b, ans_a, ans_b));
            }
        } else if (type == "?") {
            int r;
            if (!(cin >> r)) {
                finish(_wa, "Invalid query format");
            }
            if (r < 1 || r > n) {
                finish(_wa, format("Query root %d out of bounds", r));
            }

            queries++;
            
            if (queries % 2000 == 0) log_metrics();
            
            if (queries > hard_cap) {
                finish(_pe, "Too many queries (hard cap exceeded)");
            }

            
            int ans = get_median(a, b, r);
            cout << ans << endl;
            cout.flush();
        } else {
            finish(_wa, format("Unknown token '%s'", type.c_str()));
        }
    }

    return 0;
}


Test generator (C++):








#include "testlib.h"
#include <bits/stdc++.h>

using namespace std;

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

    
    
    string mode = opt<string>("mode", "non");

    
    long long seed_val = 0;
    if (argc > 1) seed_val = atoll(argv[1]);

    int n;
    int type; 

    
    if (seed_val == 1) {
        n = 4; type = 0; 
    } else if (seed_val == 2) {
        n = 5; type = 0; 
    } else if (seed_val == 3) {
        n = 100000; type = 1; 
    } else if (seed_val == 4) {
        n = 100000; type = 2; 
    } else {
        
        
        if (rnd.next(3) > 0) n = rnd.next(90000, 100000);
        else n = rnd.next(10, 100000);
        
        type = rnd.next(0, 4);
    }

    
    if (n < 1) n = 1;

    
    vector<pair<int, int>> edges;
    if (n > 1) {
        if (type == 0) { 
            for (int i = 1; i < n; i++) {
                edges.push_back({i, rnd.next(0, i - 1)});
            }
        } else if (type == 1) { 
            for (int i = 1; i < n; i++) {
                edges.push_back({i, i - 1});
            }
        } else if (type == 2) { 
            for (int i = 1; i < n; i++) {
                edges.push_back({i, 0});
            }
        } else if (type == 3) { 
            int len = rnd.next(1, n);
            
            for (int i = 1; i < len; i++) {
                edges.push_back({i, i - 1});
            }
            
            for (int i = len; i < n; i++) {
                edges.push_back({i, rnd.next(0, len - 1)});
            }
        } else if (type == 4) { 
            for (int i = 1; i < n; i++) {
                
                edges.push_back({i, rnd.wnext(i, 20)}); 
            }
        }
    }

    
    vector<int> p = rnd.perm(n); 
    vector<pair<int, int>> final_edges;
    for (auto e : edges) {
        final_edges.push_back({p[e.first] + 1, p[e.second] + 1});
    }
    
    shuffle(final_edges.begin(), final_edges.end());

    
    cout << n << endl;
    for (auto e : final_edges) {
        cout << e.first << " " << e.second << endl;
    }

    
    if (mode == "non") {
        if (n == 1) {
            
            cout << "1 1 1" << endl;
        } else {
            
            vector<vector<int>> adj(n + 1);
            for (auto e : final_edges) {
                adj[e.first].push_back(e.second);
                adj[e.second].push_back(e.first);
            }

            int a, b;
            
            
            if (rnd.next(2) == 0) {
                a = rnd.next(1, n);
                b = rnd.next(1, n);
            } else {
                
                auto bfs_far = [&](int start) {
                    queue<int> q; q.push(start);
                    vector<int> dist(n + 1, -1); dist[start] = 0;
                    int far = start;
                    while (!q.empty()) {
                        int u = q.front(); q.pop();
                        if (dist[u] > dist[far]) far = u;
                        for (int v : adj[u]) {
                            if (dist[v] == -1) {
                                dist[v] = dist[u] + 1;
                                q.push(v);
                            }
                        }
                    }
                    return far;
                };

                
                int u = bfs_far(rnd.next(1, n));
                int v = bfs_far(u);
                
                a = u;
                
                int decision = rnd.next(3);
                if (decision == 0) b = v;          
                else if (decision == 1) b = rnd.next(1, n); 
                else b = u;                        
            }

            
            queue<int> q; q.push(a);
            vector<int> parent(n + 1, 0);
            vector<bool> vis(n + 1, false);
            vis[a] = true;
            
            bool found = false;
            while (!q.empty()) {
                int u = q.front(); q.pop();
                if (u == b) { found = true; break; }
                for (int v : adj[u]) {
                    if (!vis[v]) {
                        vis[v] = true;
                        parent[v] = u;
                        q.push(v);
                    }
                }
            }

            
            vector<int> path;
            int curr = b;
            while (true) {
                path.push_back(curr);
                if (curr == a) break;
                curr = parent[curr];
            }

            
            int f = path[rnd.next(path.size())];
            
            cout << a << " " << b << " " << f << endl;
        }
    }
    
    

    return 0;
}